[ Pollard_rho ] BZOJ4802

来源:互联网 发布:linux分屏显示命令 编辑:程序博客网 时间:2024/06/05 14:32

模板题

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define ll long longll n,a[70],Ans;int i,j,k,m,c;inline ll mul(ll x,ll y,ll z){    ll Ans=0;    for(;y;y>>=1,x=(x<<1)%z)if(y&1)Ans=(Ans+x)%z;    return Ans;}inline ll Pow(ll x,ll y,ll z){    ll Ans=1;    for(;y;y>>=1,x=mul(x,x,z))    if(y&1)Ans=mul(Ans,x,z);    return Ans;}inline ll Rand(ll n){    return ((double)rand()/RAND_MAX*n+0.5);}inline bool Check(ll a,ll n){    ll t=n-1;    int s=0;    while(!(t&1))t>>=1,s++;    ll x=Pow(a,t,n),y=x;    while(s--){        x=mul(x,x,n);        if(x==1&&y!=1&&y!=n-1)return 1;        y=x;    }    return (x!=1);}inline bool MR(ll n){    if(n==2)return 1;    if(n<2||!(n%2))return 0;    for(int i=1;i<=10;i++)    if(Check(Rand(n-2)+1,n))return 0;    return 1;}inline ll Gcd(ll x,ll y){    return y?Gcd(y,x%y):x;}inline ll Pollard_rho(ll n,ll c){    ll i=1,k=2;    ll x=Rand(n-1)+1;    ll y=x;    while(1){        x=(mul(x,x,n)+c)%n;        ll d=Gcd((y-x+n)%n,n);        if(d>1&&d<n)return d;        if(x==y)return n;        if(++i==k)y=x,k<<=1;    }}inline void Find(ll n,ll c){    if(n==1)return;    if(MR(n)){        a[++m]=n;        return;    }    ll t=n,k=c;    while(t==n)t=Pollard_rho(t,c--);    Find(t,k);Find(n/t,k);}int main(){    srand(23333333);    cin>>n;    Find(n,150);    sort(a+1,a+m+1);m=unique(a+1,a+m+1)-a-1;    Ans=n;    for(i=1;i<=m;i++)Ans=Ans/a[i]*(a[i]-1);    cout<<Ans<<endl;    return 0;}
原创粉丝点击