Pollard-Rho

Pollard Rho

从未如此美妙的开局,请为我欢呼,为我喝彩,ok?

快速乘使用黑科技,取前\(12\)个质数可以保证正确性,注意Pollardt++ % 40不要打错。

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define vi vector<ull> 
using namespace std;
template <typename T>
inline void read(T &x) {
	x = 0; int f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
	if(f) x = ~x + 1;
}
using LL = long long;
using ull = unsigned long long;
ull mul(ull x, ull y, ull P) {
	LL res = x * y - P * ull(1.L / P * x * y);
	return res + P * (res < 0) - P * (res >= (LL)P);
}
ull fpow(ull x, ull pnt, ull P) {
	if(x >= P) x %= P;
	ull res = 1;
	for(; pnt; pnt >>= 1, x = mul(x, x, P)) 
		if(pnt & 1) res = mul(res, x, P);
	return res;
} 
const ull A[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; 
bool isPrime(ull n) {
	if(n < 3 || !(n & 1)) return n == 2;
	ull s = __builtin_ctz(n - 1), t = n >> s;
	for(ull a : A) {
		ull p = fpow(a, t, n), i = s;
		while(p != 1 && p != n - 1 && a % n && i--) 
			p = mul(p, p, n);
		if(p != n - 1 && i != s) return false;
	}
	return true;
}
ull pollard(ull n) {
	auto f = [n](ull x) {return mul(x, x, n) + 1;};
	ull x = 0, y = 0, t = 30, prd = 2, i = 1, q;
	while(t++ % 40 || __gcd(prd, n) == 1) {
		if(x == y) x = ++i, y = f(x);
		if((q = mul(prd, max(x, y) - min(x, y), n))) prd = q;
		x = f(x), y = f(f(y));
	}
	return __gcd(prd, n);
}
vi factor(ull n) {
	if(n == 1) return {};
	if(isPrime(n)) return {n};
	ull x = pollard(n);
	auto l = factor(x), r = factor(n / x);
	for(auto x : r) l.emplace_back(x);
	return l;
}
int T;
int main() {
	read(T);
	while(T--) {
		ull n;
		read(n);
		vi fac = factor(n);
		ull ans = 0;
		for(auto i : fac) ans = max(ans, i);
		if(ans == n) puts("Prime");
		else printf("%llu\n",ans);
	}
}
posted @ 2022-11-14 20:49  DCH233  阅读(33)  评论(0编辑  收藏  举报