码迷,mamicode.com
首页 > 其他好文 > 详细

大数分解,大数判定综合模板

时间:2016-08-11 22:21:35      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

通过poj1811整理这些算法的模板

所有代码如下:

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 using namespace std;
  6 #define LL long long
  7 const int maxs = 10000000+5;
  8 //对于1要外加特判,否则会运行错误
  9 //用小素数表做随机种子
 10 __int64 pri[25] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
 11 __int64 ans[maxs],flag;
 12 //ans数组记录分解质因数的结果(没有顺序),flag记录质因数的个数,相同的质因数不合并!
 13 
 14 //最大公约数
 15 __int64 gcd(__int64 a,__int64 b)
 16 {
 17     while(b!=0)
 18     {
 19         __int64 r = a%b;
 20         a=b;
 21         b=r;
 22     }
 23     return a;
 24 }
 25 //乘法快速幂a*b%n,不写连乘是防止相乘时溢出
 26 __int64 multi(__int64 a,__int64 b,__int64 n)
 27 {
 28     __int64 temp = 0;
 29     while(b!=0)
 30     {
 31         if(b%2==1)
 32         {
 33             temp+=a;
 34             if(temp>=n)
 35                 temp-=n;
 36         }
 37         a*=2;
 38         if(a>=n)
 39             a-=n;
 40         b/=2;
 41     }
 42     return temp;
 43 }
 44 //乘方快速幂a^n%m
 45 __int64 multimod(__int64 a,__int64 n,__int64 m)
 46 {
 47     __int64 ans=1;
 48     while(n!=0)
 49     {
 50         if(n%2==1)
 51             ans=multi(ans,a,m);
 52         a=multi(a,a,m);
 53         n/=2;
 54     }
 55     return ans;
 56 }
 57 
 58 //判断大数是否为素数(米勒罗宾算法)
 59 //调用multimod(),multi()函数
 60 bool miller_rabin(__int64 n)
 61 {
 62     if(n<2)
 63         return false;
 64     if(n==2)
 65         return true;
 66     if(n%2==0)
 67         return false;
 68     __int64 k = 0,m,a,i,j;
 69     m=n-1;
 70     while(m%2==0)
 71     {
 72         m=m/2;
 73         k++;
 74     }
 75     for(i=0;i<10;i++)
 76     {
 77         if(pri[i]>=n)
 78             return true;
 79         a = multimod(pri[i],m,n);
 80         if(a==1)
 81             continue;
 82         for(j=0;j<k;j++)
 83         {
 84             if(a==n-1)
 85                 break;
 86             a = multi(a,a,n);
 87         }
 88         if(j==k)
 89             return false;
 90     }
 91     return true;
 92 }
 93 //寻找因数
 94 __int64 pollard_rho(__int64 c,__int64 n)
 95 {
 96     __int64 i,x,y,k,d;
 97     i=1;
 98     x = y = rand()%n;
 99     k=2;
100     do
101     {
102         i++;
103         d = gcd(n+y-x,n);
104         if(d>1&&d<n)
105             return d;
106         if(i==k)
107         {
108             y=x;
109             k=k*2;
110         }
111         x = (multi(x,x,n)+n-c)%n;
112     }while(y!=x);
113     return n;
114 }
115 //递归分解,把大整数n分解保存到ans全局数组中,保存的是质因数
116 //且这些质因数没有保证顺序,也没有排重
117 void rhoAll(__int64 n)
118 {
119     if(miller_rabin(n))
120     {
121         ans[flag]=n;
122         flag++;
123         return;
124     }
125     __int64 t = n;
126     while(t>=n)
127     {
128         //随机取出一个因子,不一定是素数,也不确定大小
129         t = pollard_rho(rand()%(n-1)+1,n);
130     }
131     rhoAll(t);
132     rhoAll(n/t);
133     return;
134 }
135 
136 //返回大整数n最小的质因数
137 __int64 rho(__int64 n)
138 {
139     if(miller_rabin(n))
140         return n;
141     __int64 t = n;
142     while(t>=n)
143     {
144         t = pollard_rho(rand()%(n-1)+1,n);
145     }
146     __int64 a = rho(t);
147     __int64 b = rho(n/t);
148     return a<b?a:b;
149 }
150 int main()
151 {
152     //freopen("in.txt","r",stdin);
153     int T;
154     scanf("%d",&T);
155     while(T--)
156     {
157         flag = 0;
158         __int64 n;
159         scanf("%I64d",&n);
160         if(miller_rabin(n))//是素数
161             printf("Prime\n");
162         else
163         {
164             rhoAll(n);//把大数n分解成质因数
165             printf("%I64d\n",rho(n));//最小的质因数
166         }
167         for(int i=0;i<flag;i++)//输出这些质因数
168             printf("%I64d\n",ans[i]);
169     }
170     return 0;
171 }

 

大数分解,大数判定综合模板

标签:

原文地址:http://www.cnblogs.com/wt20/p/5762601.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!