• [BZOJ 4802]欧拉函数(Pollard_rho+Miller_Rabin)


    Description

    已知N,求phi(N)

    Solution

    数据范围非常大所以分解质因数做,Pollard rho+Miller Rabin的板子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<map>
    using namespace std;
    typedef long long LL;
    LL ans;
    map<LL,bool>have;
    LL mul(LL a,LL b,LL p)
    {
        LL res=0;
        while(b)
        {
            if(b&1)res=(res+a)%p;
            a=(a+a)%p;b>>=1;
        }
        return res;
    }
    LL pow(LL a,LL n,LL p)
    {
        LL res=1;
        while(n)
        {
            if(n&1)res=mul(res,a,p);
            a=mul(a,a,p);n>>=1;
        }
        return res;
    }
    LL gcd(LL a,LL b)
    {
        return b?gcd(b,a%b):a;
    }
    bool check(LL a,LL m,LL n,LL cnt)
    {
        LL x=pow(a,m,n),y=x;
        for(int i=1;i<=cnt;i++)
        {
            x=mul(x,x,n);
            if(x==1&&y!=1&&y!=n-1)return 1;
            y=x;
        }
        return x!=1;
    }
    bool Miller_Rabin(LL n)
    {
        if(n==2)return 1;
        if(n&1==0||n<=1)return 0;
        LL m=n-1,cnt=0;
        while(m&1==0)cnt++,m>>=1;
        for(int i=1;i<=7;i++)
        {
            if(check(rand()%(n-1)+1,m,n,cnt))
            return 0;
        }
        return 1;
    }
    LL rho(LL a,LL n,LL c)
    {
        LL i=1,k=2,x=a,y=x,d;
        while(1)
        {
            x=(mul(x,x,n)+c)%n;
            d=x>y?gcd(x-y,n):gcd(y-x,n);
            if(d>1)return d;
            if(x==y)return n;
            if(i==k)y=x,k<<=1;
            i++;
        }
    }
    void Pollard_rho(LL n)
    {
        if(n==1)return;
        if(Miller_Rabin(n))
        {
            if(!have[n])ans=ans/n*(n-1);
            have[n]=1;
            return;
        }
        LL p=n;
        while(p==n)p=rho(rand()%(n-1)+1,n,rand()%(n-1)+1);
        Pollard_rho(p),Pollard_rho(n/p);
    }
    int main()
    {
        LL N;
        scanf("%lld",&N);
        ans=N;
        srand(299792458);
        Pollard_rho(N);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    ACdream 1114(莫比乌斯反演)
    ACdream 1148(莫比乌斯反演+分块)
    bzoj2301(莫比乌斯反演+分块)
    hdu1695(莫比乌斯反演)
    hdu4908(中位数)
    bzoj1497(最小割)
    hdu3605(最大流+状态压缩)
    【Leetcode】Add Two Numbers
    【Leetcode】Add Binary
    【Leetcode】Single Number II
  • 原文地址:https://www.cnblogs.com/Zars19/p/6842763.html
Copyright © 2020-2023  润新知