How many prime numbers HDU - 2138 (Miller-Rabin測試)
阿新 • • 發佈:2018-11-10
題意:給出一組數,測試這組數一共有多少個素數
題解:要測試N是否為素數,首先將N-1分解為(2^s)*d。在每次測試開始時,先隨機選一個介於[1,N-1]的整數a,如果對所有的r屬於[0,s-1]都滿足a^dmodN不等於1&&a^((2^r)*d)modN不等於-1,則N是合數,否則,N有3/4的機率為素數。為了提高測試的正確性,可以選擇不同的a進行多次測試。
附上程式碼:
#include<bits/stdc++.h> using namespace std; //Miller-Rabin測試 //複雜度O(logn) typedef long long ll; ll pow_mod(ll a,ll i,ll n) { if(i==0){ return 1%n; } ll temp=pow_mod(a,i>>1,n); temp=temp*temp%n; if(i&1){ temp=temp*a%n; } return temp; } bool test(ll n,ll a,ll d) { if(n==2){ return true; } if(n==a){ return true; } if((n&1)==0){ return false; } while(!(d&1)){ d=d>>1; } ll t=pow_mod(a,d,n); while((d!=n-1)&&(t!=1)&&(t!=n-1)){ t=(ll)t*t%n; d=d<<1; } return (t==n-1||(d&1)==1); } bool isprime(ll n) { if(n<2){ return false; } int a[]={2,3,61}; for(int i=0;i<=2;i++){ if(!test(n,a[i],n-1)){ return false; } } return true; } int main() { ll n,temp; while(scanf("%lld",&n)!=EOF){ ll res=0; for(int i=0;i<n;i++){ scanf("%lld",&temp); if(isprime(temp)){ res++; } } printf("%lld\n",res); } return 0; }