pollard-rho分解质因数。
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define LL long long
LL a[100];
int tot;
LL Rand(LL n)
{
return (((LL)rand()<<31)|rand())%(n-1)+1;
}
LL inc(LL x,LL y,LL p)
{
x+=y;
return x>=p?x-p:x;
}
LL dec(LL x,LL y,LL p)
{
x-=y;
return x<0?x+p:x;
}
LL mul(LL x,LL y,LL p)
{
LL ret=0;
for (;y;y>>=1,x=inc(x,x,p))
if (y&1) ret=inc(ret,x,p);
return ret;
}
LL pow(LL x,LL y,LL p)
{
LL ret=1;
for (;y;y>>=1,x=mul(x,x,p))
if (y&1) ret=mul(ret,x,p);
return ret;
}
LL gcd(LL x,LL y)
{
return y?gcd(y,x%y):x;
}
int check(LL n)
{
LL x=n-1,y,z;
int k=0;
while (!(x&1))
{
x>>=1;
k++;
}
for (int i=1;i<=5;i++)
{
y=pow(Rand(n),x,n);
for (int j=1;j<=k;j++)
{
z=mul(y,y,n);
if (z==1&&y!=1&&y!=n-1) return 0;
y=z;
}
if (y!=1) return 0;
}
return 1;
}
void solve(LL n)
{
if (check(n))
{
a[++tot]=n;
return;
}
LL x,y,c,d;
x=y=Rand(n);
c=Rand(n);
for (int i=1,k=1;;i++)
{
x=inc(mul(x,x,n),c,n);
d=gcd(dec(x,y,n),n);
if (d==n)
{
solve(n);
return;
}
if (d>1)
{
solve(d);
solve(n/d);
return;
}
if (i==k)
{
y=x;
k<<=1;
}
}
}
int main()
{
LL n;
scanf("%lld",&n);
if (n==1)
{
printf("1\n");
return 0;
}
solve(n);
sort(a+1,a+tot+1);
for (int i=1;i<=tot;i++)
if (a[i]!=a[i-1]) n=n/a[i]*(a[i]-1);
printf("%lld\n",n);
}