poj 1811 Prime Test

本文介绍了一种用于判断大整数是否为素数的方法,并实现了若非素数则找到其最小素因子的功能。主要使用了Miller-Rabin素性测试与Pollard's Rho因数分解算法。

http://162.105.81.212/JudgeOnline/problem?id=1811

//对于一个数(2<=0<=2^54), 如果是素数,输出"Prime", 否则输出他的最小素因子.

//同样的程序, 第一次提交RE, 第二次提交922ms...汗

import java.util.Random; import java.util.Scanner; public class Main { static int MAX_COUNT = 6; static long allFactor[] = new long[65]; static int nFactor; static Random rn = new Random(); static long fMultiModular(long a, long b, long n) { long back = 0, temp = a % n; while(b > 0) { if((b & 0x1) == 1) { if((back = back + temp) > n) back -= n; } if((temp <<= 1) > n) temp -= n; b >>= 1; } return back; } static long GCD(long a, long b) { int z = 0; while(b != 0 && a != 0) { while((a & 1) == 0 && (b & 1) == 0) { z++; a >>= 1; b >>= 1; } while((a & 1) == 0) { a >>= 1; } while((b & 1) == 0) { b >>= 1; } if(a > b) { a -= b; } else { b -= a; } } if(b == 0) return a << z; return b << z; } static long modular_exp(long a, long b, long n) { long d = 1, dTemp = (a % n); while(b > 0) { if((b & 0x1) == 1) d = fMultiModular(d, dTemp, n); dTemp = fMultiModular(dTemp, dTemp, n); b >>= 1; } return d; } static boolean fWitNess(long a, long n, int t, long u) { long x, y = 0; x = modular_exp(a, u, n); while(t-- > 0) { y = fMultiModular(x, x, n); if(y == 1 && x != 1 && x != n - 1) return true; x = y; } return y != 1; } static boolean miller_rabin(long n, int count) { if(n == 1) return false; if(n == 2) return true; long a, u; int t = 0; for(u = n - 1; !((u & 0x1) == 1); u >>= 1) ++t; for(int i = 1; i <= count; ++i) { a = rand() % (n - 1) + 1; if(fWitNess(a, n, t, u)) return false; } return true; } static long pollard_rho(long c, long num) { int i = (1), k = (2); long x = rand() % num; long y = x, comDiv; do { ++i; if((x = fMultiModular(x, x, num) - c) < 0) x += num; if(x == y) break; comDiv = GCD((y - x + num) % num, num); if(comDiv > 1 && comDiv < num) return comDiv; if(i == k) { y = x; k <<= 1; } } while(true); return num; } static void fFindFactor(long num) { if(miller_rabin(num, MAX_COUNT) == true) { allFactor[++nFactor] = num; return; } long factor; do { factor = pollard_rho(rand() % (num - 1) + 1, num); } while(factor >= num); fFindFactor(factor); fFindFactor(num / factor); } static long rand() { long temp = rn.nextLong(); if(temp < 0) temp += Long.MAX_VALUE; return temp; } public static void main(String args[]) { int t, i; Scanner cin = new Scanner(System.in); long test_num, min; t = cin.nextInt(); while(t-- > 0) { test_num = cin.nextLong(); if(miller_rabin(test_num, 20)) System.out.println("Prime"); else { min = test_num; nFactor = 0; fFindFactor(test_num); for(i = 1; i <= nFactor; i++) { if(allFactor[i] < min) min = allFactor[i]; } System.out.println(min); } } } }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值