BZOJ 4802: 欧拉函数

Description

求\(\varphi(n),n\leqslant 10^{18}\)

Solution

数论+Miller_Rabin+Pollard_rho..

啊qwq...

Code

/**************************************************************
    Problem: 4802
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:100 ms
    Memory:1296 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
typedef long long LL;
 
namespace NT {
    inline LL Mul(LL a,LL b,LL p){
        if(p<=1000000000) return a*b%p;
        return (a*b-(LL)(a/(long double)p*b+1e-3)*p+p)%p;
    }
    inline LL Pow(LL a,LL b,LL p,LL r=1) { for(;b;b>>=1,a=Mul(a,a,p))
        if(b&1) r=Mul(r,a,p);return r; }
    int chk(LL a,LL d,LL s,LL p) {
        a=Pow(a,d,p),d=a;
        for(int i=1;i<=s;i++) {
            a=Mul(a,a,p);
            if(a==1 && d!=p-1 && d!=1) return 0;
            d=a;
        }return a==1;
    }
    int MR(LL p) {
        if(p<=1) return 0;
        if(p==2) return 1;
        if(!(p&1)) return 0;
        LL d=p-1,s=0;
        for(;!(d&1);d>>=1,s++);
        for(int i=0;i<10;i++) if(!chk(rand()%(p-1)+1,d,s,p)) return 0;
        return 1;
    }
    LL gcd(LL a,LL b) { return !b?a:gcd(b,a%b); }
    LL Div(LL p,LL c) {
        LL x=rand()%p,y=x,t=1;
        for(int i=1,k=2;t==1;i++) {
            x=(Mul(x,x,p)+c)%p;
            t=gcd(abs(x-y),p);
            if(i==k) y=x,k<<=1;
        }return t;
    }
    void PR(LL p,vector<LL> &mx) {
        if(p==1) return;
        if(MR(p)) { mx.push_back(p);return; }
        LL tmp=p;
        for(;tmp==p;tmp=Div(p,rand()%(p-1)+1));
        PR(tmp,mx),PR(p/tmp,mx);
    }
}
 
LL n,ans;
vector<LL> pr;
int main() {
    scanf("%lld",&n);
    NT::PR(n,pr);
    sort(pr.begin(),pr.end());
    ans=n;
    for(int i=0,j;i<(int)pr.size();i=j+1) {
        for(j=i;pr[j+1]==pr[i];j++);
        ans/=pr[i];ans*=pr[i]-1;
    }printf("%lld\n",ans);
    return 0;
}

  

posted @ 2017-04-19 10:01  北北北北屿  阅读(185)  评论(0编辑  收藏  举报