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

通过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 }
时间: 2024-08-03 15:38:51

大数分解,大数判定综合模板的相关文章

POJ1811 Prime Test(miller素数判断&amp;&amp;pollar_rho大数分解)

http://blog.csdn.net/shiyuankongbu/article/details/9202373 发现自己原来的那份模板是有问题的,而且竟然找不出是哪里的问题,所以就用了上面的链接上的一份代码,下面只是寄存一下这份代码,以后打印出来当模板好了. #pragma warning(disable:4996) #include <iostream> #include <cstring> #include <algorithm> #include <c

POJ 2429 GCD &amp; LCM Inverse (大数分解)

GCD & LCM Inverse 题目:http://poj.org/problem?id=2429 题意: 给你两个数的gcd和lcm,[1, 2^63).求a,b.使得a+b最小. 思路: lcm = a * b / gcd 将lcm/gcd之后进行大数分解,形成a^x1 * b^x2 * c^x3-- 的形式,其中a,b,c为互不相同的质数.然后暴力枚举即可. 代码: #include<map> #include<set> #include<queue>

POJ 2429 GCD &amp;amp; LCM Inverse (大数分解)

GCD & LCM Inverse 题目:http://poj.org/problem? id=2429 题意: 给你两个数的gcd和lcm,[1, 2^63). 求a,b.使得a+b最小. 思路: lcm = a * b / gcd 将lcm/gcd之后进行大数分解.形成a^x1 * b^x2 * c^x3-- 的形式.当中a,b,c为互不同样的质数.然后暴力枚举就可以. 代码: #include<map> #include<set> #include<queue&

light oj 1236 【大数分解】

给定一个大数,分解质因数,每个质因子的个数为e1,e2,e3,--em, 则结果为((1+2*e1)*(1+2*e2)--(1+2*em)+1)/2. //light oj 1236 大数分解素因子 #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <ctype.h> #i

poj1181 大数分解

1 //Accepted 164 KB 422 ms 2 //类似poj2429 大数分解 3 #include <cstdio> 4 #include <cstring> 5 #include <ctime> 6 #include <time.h> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 const __int64 inf = 1L

poj 2429 Pollard_rho大数分解

先对lcm/gcd进行分解,问题转变为从因子中选出一些数相乘,剩下的数也相乘,要求和最小. 这里可以直接搜索,注意一个问题,由于相同因子不能分配给两边(会改变gcd)所以可以将相同因子合并,这样的话,搜索的层数也变的很少了. #include<stdio.h> #include<string.h> #include<iostream> #include<math.h> #include<stdlib.h> #include<time.h&g

POJ 2447 RSA 大数分解+逆元+快速幂

链接:http://poj.org/problem?id=2447 题意: 思路:Pollard_Rho质数分解,得到两个素数因子,P,Q,求出T,E,快速幂即可得M. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <map> #include <cstdlib> #include <queue>

Prime Test POJ - 1811(素性检测+大数分解)

Prime Test POJ - 1811 题意:判断N (2 <= N < 2 54) 是不是素数,如果不是求它的最小素因数. millerRabin素性检测 + pollard rho大数分解 链接 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 #define LL l

高精度之大数乘大数

上一篇说了简单的大数乘以小数的问题,绝大多数的问题解决不了. 现在我们来说一下大数乘以大数. 大数乘以大数也是用来模拟手算. 举个例子吧! 先从个位开始一个一个的乘 乘完个位然后再乘十位,乘十位的时候要和个位的想成的结果相加. 这里注意乘十位的时候 就不要和乘个位数字的结果中的最后一位相加了 .就是如图搓位. 就是这样 . 下面先贴上我的代码. #include<iostream> #include<string.h> using namespace std; void mult(