UVA1434 YAPTCHA 题解
题目大意:
令 \(S_n=\sum\limits^n_{k=1}\lfloor\dfrac{(3k+6)!+1}{3k+7}-\lfloor\dfrac{(3k+6)!}{3k+7}\rfloor\rfloor\) ,给定整数 \(n\) ,求出 \(S_n\) 的值(\(1 \leq n \leq 10^6\))
前置知识:威尔逊定理
\(\large p\) 为质数\(\Leftrightarrow\large{\left(p-1\right)!\equiv -1 \left(\mod p\right)}\)
具体证明可参考此篇文章,链接
主要思路:
令 \(f(k)=\lfloor\dfrac{(3k+6)!+1}{3k+7}-\lfloor\dfrac{(3k+6)!}{3k+7}\rfloor\rfloor\),\(S_n=\sum\limits^n_{k=1}f(k)\),所以我们只需算出 \(f(k)\) 后再做一个前缀和就可求出 \(S_n\)
由威尔逊定理可得,当 \(3k+7\) 为质数时,\((3k+6)! \equiv -1 \left(\mod 3k+7 \right)\),所以,\((3k+7) \mid ((3k+6)!+1)\),此时 \(\dfrac{(3k+6)!+1}{3k+7}\) 为整数。令 \(t = \dfrac{(3k+6)!+1}{3k+7}\),则有 \(\lfloor\dfrac{(3k+6)!}{3k+7}\rfloor=\lfloor t - \dfrac{1}{3k+7}\rfloor\),又因为 \(3k+7 \geq 7\),所以 \(0<\dfrac{1}{3k+7} < 1\),则 \(t-1< t - \dfrac{1}{3k+7} < t\),\(\lfloor t - \dfrac{1}{3k+7}\rfloor=t-1\)。综上,当 \(3k+7\) 为质数时,\(f_k=\lfloor t-(t-1)\rfloor=1\)。
当 \(3k+7\) 为合数时, \((3k+7) \nmid ((3k+6)!+1)\),所以 \(\lfloor\dfrac{(3k+6)!+1}{3k+7}\rfloor=\lfloor\dfrac{(3k+6)!}{3k+7}\rfloor\),\(f_k= \lfloor\dfrac{(3k+6)!+1}{3k+7}-\lfloor\dfrac{(3k+6)!}{3k+7}\rfloor\rfloor=\lfloor\dfrac{(3k+6)!+1}{3k+7}-\lfloor\dfrac{(3k+6)!+1}{3k+7}\rfloor\rfloor=0\)
综合这两种情况,我们可以得出 \(f(k)= [3k+7\)为质数\(]\)。所以,我们只需要先进行一次线性筛,筛出 \(\left[1,3\times10^6+7\right]\) 中所有的质数,就可以得出所有的 \(f(k)\) ,进而求出所有的 \(S_n\) 。时间复杂度 \(O(n)\)。
代码:
// =============================================
// 暁の水平线に胜利を刻むのです!
// Author: 佐世保の时雨
// Blog: https://www.cnblogs.com/SasebonoShigure
// =============================================
#include <cstdio>
#include <bitset>
#include <iostream>
using namespace std;
const int Maxn = 6e6 + 10, Mod = 9901;
int T, n, Count;
int Prime[Maxn], Tag[Maxn], f[Maxn];
inline void Getprime (const int n) {
for (int i = 2; i <= n; ++ i ) {
if (!Tag[i] ) {
Prime[++ Count] = i;
}
for (int j = 1; j <= Count and i * Prime[j] <= n; ++ j ) {
Tag[i * Prime[j]] = 1;
if (i % Prime[j] == 0 ) {
break ;
}
}
}
return ;
}
signed main () {
Getprime (5e6), n = 1e6;
for (int i = 1; i <= n; ++ i ) {
if (!Tag[i * 3 + 7] ) {
f[i] = 1;
}
}
for (int i = 1; i <= n; ++ i ) {
f[i] += f[i - 1];
}
scanf ("%d", &T);
while (T -- ) {
scanf ("%d", &n), printf ("%lld\n", f[n]);
}
return 0;
}
后话:
这题难度顶多就算提高+吧……
但能水一道紫题那自然是最好的!

浙公网安备 33010602011771号