求1018范围内的数的欧拉函数
我选择死亡
emmmm
倒是有思路
分解质因数
利用欧拉函数的性质求值
但是
数太大了我不会qwq
于是这个时候
就要用
完全不会现在也没明白的
Miller-Rabin和Pollard-rho
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<climits>
#include<string>
#include<cstdlib>
#include<ctime>
#define MOD 1000000007
#define LL long long
using namespace std;
LL num[10005],tot;
LL Rand(LL p)
{
return (((LL)rand()<<31)|rand())%(p-1)+1;
}
LL inc(LL a,LL b,LL mod)
{
a+=b;
if(a>=mod) return a-mod;
return a;
}
LL dec(LL a,LL b,LL mod)
{
a-=b;
if(a<0) return a+mod;
return a;
}
LL mul(LL a,LL b,LL mod)
{
LL tmp=0;
while(b)
{
if(b&1) tmp=inc(tmp,a,mod);
a=inc(a,a,mod);
b>>=1;
}
return tmp;
}
LL pow(LL a,LL b,LL mod)
{
LL tmp=1;
while(b)
{
if(b&1) tmp=mul(tmp,a,mod);
a=mul(a,a,mod);
b>>=1;
}
return tmp;
}
LL gcd(LL a,LL b)
{
if(!b) return a;
return gcd(b,a%b);
}
bool check(LL p)
{
LL x=p-1,y,z,k=0;
while(!(x&1))
{
x>>=1;
k++;
}
for(LL i=1;i<=5;i++)
{
y=pow(Rand(p),x,p);
for(LL j=1;j<=k;j++)
{
z=mul(y,y,p);
if((z==1)&&(y!=1)&&(y!=p-1)) return 0;
y=z;
}
if(y!=1) return 0;
}
return 1;
}
void solve(LL x)
{
if(check(x))
{
tot++;
num[tot]=x;
return;
}
LL a,b,c,d;
a=b=Rand(x);
c=Rand(x);
for(LL i=1,k=1;;i++)
{
a=inc(mul(a,a,x),c,x);
d=gcd(dec(a,b,x),x);
if(d==x)
{
solve(x);
return;
}
if(d>1)
{
solve(d);
solve(x/d);
return;
}
if(i==k)
{
b=a;
k<<=1;
}
}
}
int main()
{
freopen("phi.in","r",stdin);
freopen("phi.out","w",stdout);
LL n,t;
srand(time(0));
scanf("%lld",&n);
if(n==1)
{
printf("1");
return 0;
}
solve(n);
sort(num+1,num+tot+1);
for(LL i=1;i<=tot;i++)
if (num[i]!=num[i-1]) n=n/num[i]*(num[i]-1);
printf("%lld",n);
return 0;
}