hdu 2973"YAPTCHA"(威尔逊定理)
题意:
给出自然数 n,计算出 Sn 的值,其中 [ x ]表示不大于 x 的最大整数。
题解:
根据威尔逊定理,如果 p 为素数,那么 (p-1)! ≡ -1(mod p),即 (p-1)! + 1 = p*q.
令 f(K) =
①如果 3K+7 为素数,则 (3K+7-1)! ≡ -1(mod 3K+7),即 (3K+6)! = (3K+7)*q -1.
那么表达式 可化简为 [ (3K+7)*q / (3K+7) - 1 / (3K+7) ] = [ q - 1 / (3K+7)].
易得 q-1 < q - 1 / (3K+7) < q ,所以=q-1,那么 f(K) = q-(q-1) = 1.
②如果 3K+7 为合数,则 (3K+6)! 能被 (3K+7) 整除,f(K) = 0;
由此,本题转化为求解K在[1,n]范围内 (3K+7) 的素数个数。
对②的证明:
令p=a*b,(1<a<=b) ①若a!=b,则(p-1)!=1*2*..*a*..*b*..*(p-1),显然 (a*b) | (p-1)!; ②若a==b且为素数,则当a>2时,a*b=a*a>2*a, 若p>4,则(p-1)! = 1*2*..*a*..*(2a)*..(p-1),同样有(a*b)|(p-1)!; 综上,如果p为合数,则 p | (p-1)!;
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 const int maxn=1e6+10; 6 7 int n; 8 int ans[maxn];//ans[i]:[1,i]中,满足 3K+7 为素数的整数个数 9 10 bool isPrime(int num) 11 { 12 int x=sqrt(num); 13 for(int i=2;i <= x;++i) 14 if(num%i == 0) 15 return 0; 16 return 1; 17 } 18 void primeTable() 19 { 20 ans[1]=0; 21 for(int i=2;i < maxn;++i)//离散计算出所有的结果 22 ans[i]=ans[i-1]+isPrime(3*i+7); 23 } 24 int main() 25 { 26 int test; 27 scanf("%d",&test); 28 primeTable(); 29 while(test--) 30 { 31 scanf("%d",&n); 32 printf("%d\n",ans[n]); 33 } 34 return 0; 35 }