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;
}

后话:

这题难度顶多就算提高+吧……
但能水一道紫题那自然是最好的!

posted @ 2021-10-14 16:10  佐世保の时雨酱  阅读(65)  评论(0)    收藏  举报