Millar-Rabin +Pollard Rho
我的MR在输入2的时候会挂,因为模0了;
我的PR在输入4的时候会挂,因为出现一点偏差详见代码注释……
关于Pollard Rho推荐:https://wenku.baidu.com/view/3db5c7a6ad51f01dc381f156.html
我也不知道为什么那样子做复杂度是对的…..
实测,像什么x = x * 2333 + c的函数都不如文章里说的x = x * x + c来得快,感觉挺玄学……没找到什么文献,如果有相关的东西求告知……
#include<cstdio>
#include<algorithm>
using namespace std;
namespace runzhe2000
{
typedef unsigned long long ll;
ll n, cur; const ll A = 20000107, B = 3333331;
ll randll(){return cur = cur * A + B;}
ll fmul(ll a, ll b, ll p)
{
ll r = 0;
for(; b; b >>= 1)
{
if(b&1)(r+=a)%=p;
(a+=a)%=p;
}
return r;
}
ll fpow(ll a, ll b, ll p)
{
ll r = 1;
for(; b; b >>= 1)
{
if(b&1)r=fmul(r,a,p);
a=fmul(a,a,p);
}
return r;
}
int MR(ll n)
{
if(n == 2) return true;
ll a = n-1, b = 0;
for(; !(a&1); a>>=1, b++);
for(int t = 10; t; t--)
{
ll x = randll()%(n-2)+2, pre;
x = pre = fpow(x, a, n);
for(int i = 0; i < (int)b; i++)
{
x = fmul(x,x,n);
if(x==1&&pre!=1&&pre!=n-1)return false;
pre = x;
}
if(x != 1) return false;
}
return true;
}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
ll PR(ll n, int c)
{
if(n == 4) return 2; //在模4意义下,两次循环以后就相等了,我也不知道为什么这么巧
ll x = 2, y = 2, p = 1;
for(; p == 1; )
{
x = fmul(x,x,n)+c;
y = fmul(y,y,n)+c;
y = fmul(y,y,n)+c;
if(x == y) return n;
p = gcd(n, (y-x+n)%n);
}
return p;
}
ll ans, q[2333333]; int tail;
void find(ll x, int c)
{
if(x == 1) return;
if(MR(x))q[tail++] = x;
else
{
ll p = x;
for(; p==x; ) p = PR(x,c++);
find(x/p, c); find(p, c);
}
}
void main()
{
int T; scanf("%d",&T);
for(; T--; )
{
scanf("%lld",&n);
tail = ans = 0; find(n,1);
sort(q, q+tail); int cnt = 0;
ll tmp = 0;
for(int i = 0; i < tail; i++)
{
if(q[i] != q[i-1])
{
ans += tmp;
++cnt;
tmp = 1;
}
tmp *= q[i];
}
ans += tmp;
if(cnt == 1) ans /= q[0];
printf("%d %lld\n",cnt, ans);
}
}
}
int main()
{
runzhe2000::main();
}