51nod 1186 质数检测(Miller-Rabin算法)

分析:用Miller-Rabin算法,预处理一些质数,取一个质数x,若n为质数,必然有x^(n-1)=1modn,但是反之不一定,若通过了前面的检验,将n-1分解为2^d*r,r为奇数,接下来检验x^(d-1)*r mod n,以此类推除二检验,直到mod的结果为-1或不能被二整除,若其中出现mod的结果不为±1,说明n不是质数.这是因为若n为质数,x<n,>x^2=1 mod n,当且仅当x=1或x=n-1.若n通过了所有的x检验,就断定它是质数.实际上这一结论有误差,但检验k个x后错误率至多为2^(-k),因此增大检验次数就能把错误率将到很低.当然得用大整数类...

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<string>
  4 #include<vector>
  5 #include<iomanip>
  6 using namespace std;
  7 const int BASE=100000000,WIDTH=8;
  8 typedef long long ll;
  9 struct BigInt{
 10     bool neg;
 11     vector<int> s;
 12     BigInt operator =(string &str){
 13         s.clear();
 14         neg=false;
 15         if(str[0]=='-'){
 16             neg=true;
 17             str[0]='0';
 18         }
 19         int x,len=(str.length()-1)/WIDTH+1;
 20         for(int i=0;i<len;i++){
 21             int end=str.length()-i*WIDTH;
 22             int start=max(0,end-WIDTH);
 23             sscanf(str.substr(start,end-start).c_str(),"%d",&x);
 24             s.push_back(x);
 25         }
 26         return *this;
 27     }
 28     BigInt operator =(int n){
 29         s.clear();
 30         if(n<0){
 31             neg=true;
 32             s.push_back(-n);
 33         }else{
 34             neg=false;
 35             s.push_back(n);
 36         }
 37         return *this;
 38     }
 39     void print(){
 40         if(neg)cout<<'-';
 41         cout<<s.back();
 42         for(int i=s.size()-2;i>=0;i--){
 43             cout<<setw(8)<<setfill('0')<<s[i];
 44         }
 45         cout<<endl;
 46     }
 47 };
 48 bool operator ==(const BigInt &a,const BigInt &b){
 49     if(a.neg!=b.neg)return false;
 50     if(a.s.size()==b.s.size()){
 51         for(int i=0;i<a.s.size();i++)
 52             if(a.s[i]!=b.s[i])return false;
 53         return true;
 54     }
 55     return false;
 56 }
 57 bool operator<(BigInt &a,BigInt &b){
 58     if(a.neg&&!b.neg)return true;
 59     if(!a.neg&&b.neg)return false;
 60     if(a.neg&&b.neg){
 61         a.neg=b.neg=false;
 62         bool ans=a<b||a==b;
 63         a.neg=b.neg=true;
 64         return !ans;
 65     }
 66     if(a.s.size()<b.s.size())return true;
 67     else if(a.s.size()>b.s.size())return false;
 68     for(int i=a.s.size()-1;i>=0;i--){
 69         if(a.s[i]==b.s[i])continue;
 70         if(a.s[i]<b.s[i])return true;
 71         return false;
 72     }
 73     return false;
 74 }
 75 bool operator >(BigInt &a,BigInt &b){return !(a==b&&a<b);}
 76 bool operator <=(BigInt &a,BigInt &b){return (a==b||a<b);}
 77 bool operator >=(BigInt &a,BigInt &b){return !(a<b);}
 78 bool operator !=(BigInt &a,BigInt &b){return !(a==b);}
 79 BigInt operator -(BigInt &a,BigInt &b);
 80 BigInt operator +(BigInt &a,BigInt &b){
 81     BigInt ans;
 82     if(a.neg&&!b.neg){
 83         a.neg=false;
 84         ans=b-a;
 85         a.neg=true;
 86         return ans;
 87     }
 88     if(!a.neg&&b.neg){
 89         b.neg=false;
 90         ans=a-b;
 91         b.neg=true;
 92         return ans;
 93     }
 94     ans.neg=a.neg;
 95     int k=0,i=0;
 96     while(i<a.s.size()||i<b.s.size()){
 97         if(i<a.s.size())k+=a.s[i];
 98         if(i<b.s.size())k+=b.s[i];
 99         ans.s.push_back(k%BASE);
100         k/=BASE;
101         i++;
102     }
103     if(k)ans.s.push_back(k);
104     return ans;
105 }
106 BigInt operator -(BigInt &a,BigInt &b){
107     BigInt ans;
108     if(!a.neg&&b.neg){
109         b.neg=false;
110         ans=a+b;
111         b.neg=true;
112         return ans;
113     }
114     if(a.neg&&!b.neg){
115         a.neg=false;
116         ans=a+b;
117         a.neg=true;
118         ans.neg=true;
119         return ans;
120     }
121     if(a.neg&&b.neg&&a>b){
122         b.neg=a.neg=false;
123         ans=b-a;
124         b.neg=a.neg=true;
125         return ans;
126     }
127     if(!a.neg&&!b.neg&&a<b){
128         ans=b-a;
129         ans.neg=true;
130         return ans;
131     }
132     ans.neg=false;
133     int k=0,i=0;
134     while(i<a.s.size()||i<b.s.size()){
135         if(i<a.s.size())k+=a.s[i];
136         if(i<b.s.size())k-=b.s[i];
137         if(k<0){
138             ans.s.push_back(k+BASE);
139             k=-1;
140         }else{
141             ans.s.push_back(k);
142             k=0;
143         }
144         i++;
145     }
146     while(ans.s.size()>1&&i>=0&&ans.s[--i]==0)ans.s.pop_back();
147     return ans;
148 }
149 BigInt operator *(BigInt &a,BigInt &b){
150     if(a.s.size()<b.s.size())return b*a;
151     BigInt ans;
152     ll k=0;
153     for(int l=0;l<a.s.size()+b.s.size()-1;l++){
154         for(int i=min(l,int(a.s.size()-1));i>=0&&l-i<b.s.size();i--){
155             k+=(ll)a.s[i]*b.s[l-i];
156         }
157         ans.s.push_back(k%BASE);
158         k/=BASE;
159     }
160     if(k)ans.s.push_back(k);
161     ans.neg=a.neg^b.neg;
162     return ans;
163 }
164 BigInt operator *(BigInt &a,int b){
165     BigInt ans;
166     ll k=0;
167     for(int l=0;l<a.s.size();l++){
168         k+=a.s[l]*b;
169         ans.s.push_back(k%BASE);
170         k/=BASE;
171     }
172     if(k)ans.s.push_back(k);
173     if((b<0&&a.neg)||(b>0&&!a.neg))ans.neg=false;
174     else ans.neg=true;
175     return ans;
176 }
177 inline void devide_2(BigInt &a){
178     int k=0;
179    // a.print();
180     for(int i=a.s.size()-1;i>=0;i--){
181         int k0=k;
182         k=a.s[i]%2==0?0:BASE/2;
183         //cout<<a.s[i]<<endl;
184         a.s[i]=k0+a.s[i]/2;
185         //cout<<a.s[i]<<endl;
186     }
187     if(a.s.back()==0)a.s.pop_back();
188 }
189 inline BigInt devide(BigInt &a,BigInt &b,BigInt &r){
190     BigInt L,R,m,t;
191     L=1;R=a;
192     if(a<b){
193         r=a;
194         return m=0;
195     }
196     while(R>L){
197         //L.print();
198         //R.print();
199         t=(R+L);
200         devide_2(t);
201         if(t==L){
202             m=t*b;
203             r=a-m;return L;
204         }
205         m=t*b;
206         //m.print();
207         if(m==a){
208             r=0;return t;
209         }else if(m<a){
210             L=t;
211         }else{
212             R=t;
213         }
214     }
215     m=t*b;
216     r=a-m;
217     return L;
218 }
219 inline BigInt operator%(BigInt &a,BigInt &b){
220     BigInt r;
221     devide(a,b,r);
222     return r;
223 }
224 inline bool Is_even(const BigInt &a){
225     if(a.s[0]%2==0)return true;
226     return false;
227 }
228 //计算n的k次方模p
229 BigInt qpow(BigInt &n,BigInt &k,BigInt &p){
230     BigInt ans,y,_n=k,a;
231     a=1;
232     //n.print();k.print();p.print();
233     ans=1;y=n;
234     while(_n>=a){
235         if(!Is_even(_n)){
236             ans=(ans*y);
237             //ans.print();
238             ans=ans%p;
239             //ans.print();
240         }
241         y=y*y;
242         //y.print();
243         y=y%p;
244         //y.print();
245         //cout<<"---------
";
246         devide_2(_n);
247        // _n.print();
248     }
249     return ans;
250 }
251 BigInt x[50];
252 int len=0;
253 void Init(){
254     int num[20];
255     for(int i=2;i<20;i++)num[i]=i;
256     for(int i=2;i<20;i++){
257         if(num[i]==0)continue;
258         x[len++]=i;
259         for(int j=2*i;j<20;j+=i)
260             num[j]=0;
261     }
262 }
263 bool Is_pri(BigInt &n){
264     if(Is_even(n)){
265         if(n.s.size()==1&&n.s[0]==2)return true;
266         return false;
267     }
268     BigInt a,b,r,u;
269     a=1;b=n-a;
270     for(int i=0;i<len;i++){
271         if(x[i]>=n)break;
272         r=b;
273         //r.print();
274         BigInt &t=x[i];
275         //t.print();
276         u=qpow(t,r,n);
277        // u.print();
278         if(u!=a)return false;
279         while(Is_even(r)){
280             devide_2(r);
281             u=qpow(t,r,n);
282             //u.print();
283             if(u!=a){
284                 if(u!=b)return false;
285                 break;
286             }
287         }
288     }
289     return true;
290 }
291 int main(){
292     //freopen("e:\out.txt","w",stdout);
293 //    BigInt a,b,r;
294 //    string s;
295 //    cin>>s;
296 //    a=s;
297 //    cin>>s;
298 //    b=s;
299 //    devide(a,b,r).print();
300 //    r.print();
301     Init();
302     BigInt n;
303     string s;
304     while(cin>>s){
305         n=s;
306         if(Is_pri(n))cout<<"Yes
";
307         else cout<<"No
";
308     }
309     return 0;
310 }
原文地址:https://www.cnblogs.com/7391-KID/p/6930087.html