若n为素数,取a<n,设n-1=d*2^r,则要么a^d≡1(mod n),要么∃0≤i<r,s.t.(s.t.是满足或使得的意思)a^(d*2^i)≡-1(mod n).
思路:找k个数,全部进行上述两个测试(至少满足一个),若都能通过测试,则可以认为n是素数。
//该方法存在一定的问题,当然,出错的概率很小。
k个数选取:一般选取8个素数(zhx选的{2,3,5,7,11,13,17,37},他说这八个数判定long long以内的素数不会出错)
实测:找出区间[x,y]中的素数个数
数据范围:1<=x<=y<=2147483647,y-x<=10^6
可以过
#include<iostream> #include<cstdio> using namespace std; int prime[8]={2,3,5,7,11,13,17,37}; int ksm(int m,int n,int p){ if(p==1)return 0; int ans=1; while(n){ if(n&1)ans=1ll*ans*m%p; m=1ll*m*m%p; n>>=1; } return ans; } bool miller_rabin(int n,int a) { int d=n-1,r=0;//跟上述内容中的字母一致 while(d%2==0) d=d>>1,r++; int z=ksm(a,d,n);//快速幂求a^d%n的值 if(z==1) return true; for(int i=0;i<r;i++) { if(z==n-1) return true; z=1ll*z*z%n; } return false; } bool check(int n) { if(n<2) return false; for(int a=0;a<8;a++)//判断n是不是素数 { if(n==prime[a])//如果该数是素数表中的(prime)里的,直接返回true return true; if(n%prime[a]==0)//如果prime里有因子,直接返回false return false; if(!miller_rabin(n,prime[a])) return false;//如果素性测试返回的是false,则证明n不是素数 } return true;//如果能走到这一步,就说明n是素数。 } int x,y; long long ans; int main() { scanf("%d%d",&x,&y); for(int i=x;i<=y;i++) { if(check(i)) ans++; } printf("%lld",ans); return 0; }