poj 1811 Prime Test——miller rabin+pollard rho
2011-09-02 17:39
399 查看
被这道题虐了两天了……自己也试着敲了一下。。事实证明手上的模版不给力啊。。。先用手上的模版敲了一个miller rabin,结果9都给我判成素数,真是无言了,然后又用算导上面讲得方法自己敲了一个pollard rho,结果卡死了……只有少数几种情况会出答案,大部分情况都是卡死了。。悲剧一个。。后来去找解体报告,因为这个题本来就是模版题嘛。。大多数写的都不是很符合我的习惯,看不进去,好不容易找到两个我看得进去的吧,自己在hust上交了一下,居然RE了。。话说这种解题报告还交上来嘛。。。好不容易在百度知道上面找到了一份代码,我觉得写得挺不错的,也解决了一些我遇到的困惑。
素数判断用miller法 分解用pollard法 关键有几点
1:用2分法作64位乘法必须用unsigned __Int64 否则位移的时候会带符号(符号位移不掉)
2:pollard会陷入死循环 所以要加卡时 如果超过多少次还没出来就return 1,换个初始数继续
3:所有<<号,>>号必须全部加括号 像b1=(x<<32)>>32这种等号后面没加括号的是错误的 应该是b1=((x<<32)>>32);
4:发现pollard算法中用x*x-1产生随机数,如果那个-1改成其他数 效率会不一样 根据frkstyc大牛的代码 x*x+16381要将近快一倍(可是这位仁兄用的是10007。。。我自己换别的数字试了一下,确实没有更快的)
素数判断用miller法 分解用pollard法 关键有几点
1:用2分法作64位乘法必须用unsigned __Int64 否则位移的时候会带符号(符号位移不掉)
2:pollard会陷入死循环 所以要加卡时 如果超过多少次还没出来就return 1,换个初始数继续
3:所有<<号,>>号必须全部加括号 像b1=(x<<32)>>32这种等号后面没加括号的是错误的 应该是b1=((x<<32)>>32);
4:发现pollard算法中用x*x-1产生随机数,如果那个-1改成其他数 效率会不一样 根据frkstyc大牛的代码 x*x+16381要将近快一倍(可是这位仁兄用的是10007。。。我自己换别的数字试了一下,确实没有更快的)
a27400 | 1811 | Accepted | 412K | 375MS | G++ | 1872B | 2011-09-02 17:07:07 |
//写得太好了,每一个函数都是一个模版呀~~~~ #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define gcc 10007 #define MAX ((INT)1<<63)-1 using namespace std; typedef unsigned long long INT; INT p[10]={2,3,5,7,11,13,17,19,23,29}; inline INT gcd(INT a,INT b) { INT m=1; if(!b) return a; while(m) { m=a%b; a=b; b=m; } return a; } //计算a*b%n inline INT multi_mod(INT a,INT b,INT mod) { INT sum=0; while(b) { if(b&1) sum=(sum+a)%mod; a=(a+a)%mod; b>>=1; } return sum; } //计算a^b%n; inline INT quickmod(INT a,INT b,INT mod) { INT sum=1; while(b) { if(b&1) sum=multi_mod(sum,a,mod); a=multi_mod(a,a,mod); b>>=1; } return sum; } bool miller_rabin(INT n) { int i,j,k=0; INT u,m,buf; //将n分解为m*2^k if(n==2) return true; if(n<2||!(n&1)) return false; m=n-1; while(!(m&1)) k++,m>>=1; for(i=0;i<9;i++) { if(p[i]>=n) return true; u=quickmod(p[i],m,n); if(u==1) continue; for(j=0;j<k;j++) { buf=multi_mod(u,u,n); if(buf==1&&u!=1&&u!=n-1) return false; u=buf; } //如果p[i]^(n-1)%n!=1那么n为合数 if(u-1) return false; } return true; } //寻找n的一个因子,该因子并不一定是最小的,所以下面要二分查找最小的那个因子 INT pollard(INT n) { INT i=1; INT x=rand()%(n-1)+1; INT y=x; INT k=2; INT d; do { i++; d=gcd(n+y-x,n); if(d>1&&d<n) return d; if(i==k) y=x,k*=2; x=(multi_mod(x,x,n)+n-gcc)%n; }while(y!=x); return n; } INT MIN; INT pollard_min(INT n) { INT p,a,b=MAX; if(n==1) return MAX; if(miller_rabin(n)) return n; p=pollard(n); a=pollard_min(p);//二分查找 INT y=n/p; b=pollard_min(y); return a<b?a:b; } int main(void) { INT T; INT n; scanf("%lld",&T); while(T--) { scanf("%lld",&n); MIN=MAX; if(miller_rabin(n)) { puts("Prime"); } else printf("%lld\n",pollard_min(n)); } return 0; }
相关文章推荐
- POJ 1811 Prime Test (miller_rabin + pollard_rho)
- POJ 1811 Prime Test(Miller-Rabin & Pollard-rho素数测试)
- [POJ 1811 Prime Test] Miller_Rabin + Pollard_rho 大数质数判断/质因子分解模板
- POJ 1811 Prime Test (Miller-Robin+Pollard_rho)
- POJ-1811 Prime Test(Miller_Rabin算法和Pollard_rho算法模板题)
- POJ1811 PrimeTest Miller-Robin+Pollard-Rho
- POJ - 1811_Prime Test_miller-rabin模板&&polard_rho模板
- POJ 1811 Prime Test(素数判定Miller-Rabin+素因子分解Pollard-rho)
- POJ1811- Prime Test(Miller–Rabin+Pollard's rho)
- Poj 1811 Prime Test 素数测试 Miller-Rabin 与 整数的因子分解 Pollard rho
- POJ 1811 Prime Test (Pollard rho 大整数分解)
- Miller_rabin算法+Pollard_rho算法 POJ 1811 Prime Test
- 【POJ1811】【miller_rabin + pollard rho + 快速乘】Prime Test
- POJ 1811 Miller_Rabin+Pollard_Rho
- POJ 1811 *** Prime Test(详解Miiler_Rabin算法与Pollard_Rho算法)
- poj 1811 Prime Test_Pollard_rho算法模板
- 数论 - Miller_Rabin素数测试 + pollard_rho算法分解质因数 ---- poj 1811 : Prime Test
- [POJ 1811]Prime Test---Miller-Rabin算法&Pollard-rho算法
- poj 1811 Pallor Rho +Miller Rabin
- <模板>(Miller-Rabin和Pollard_rho算法)poj 2429 GCD & LCM Inverse (数论)