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)!;
View Code

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
",ans[n]);
33     }
34     return 0;
35 }
View Code

  

原文地址:https://www.cnblogs.com/violet-acmer/p/10458834.html