• 51_1037最长循环节 (miller rabin算法 pollard rho算法 原根)


    1037 最长的循环节 V2

    基准时间限制:1 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
    收藏
    关注
    正整数k的倒数1/k,写为10进制的小数如果为无限循环小数,则存在一个循环节,求<=n的数中,倒数循环节长度最长的那个数。
     
    1/6= 0.1(6) 循环节长度为1
    1/7= 0.(142857) 循环节长度为6
    1/9= 0.(1)  循环节长度为1
    Input
    输入n(10 <= n <= 10^18)
    Output
    输出<=n的数中倒数循环节长度最长的那个数
    Input示例
    10
    Output示例
    7


    主要用到了两个算法:miller rabin算法 pollard rho算法, 前者是种带概率性的判断质数,适用于较大数字的判断(概率性的), 后者用于大数的因式分解

    模板代码:
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    #include <iostream>
    #include <math.h>
     
    const int Times=10;
    const int N=5500;
     
    using namespace std;
    typedef long long LL;
     
    LL ct,cnt,c,x,y;
    LL fac[N],num[N],arr[N];
     
    LL gcd(LL a,LL b)
    {
        return b? gcd(b,a%b):a;
    }
     
    LL multi(LL a,LL b,LL m)
    {
        LL ans=0;
        while(b)
        {
            if(b&1)
            {
                ans=(ans+a)%m;
                b--;
            }
            b>>=1;
            a=(a+a)%m;
        }
        return ans;
    }
     
    LL quick_mod(LL a,LL b,LL m)
    {
        LL ans=1;
        a%=m;
        while(b)
        {
            if(b&1)
            {
                ans=multi(ans,a,m);
                b--;
            }
            b>>=1;
            a=multi(a,a,m);
        }
        return ans;
    }
     
    bool Miller_Rabin(LL n)
    {
        if(n==2) return true;
        if(n<2||!(n&1)) return false;
        LL a,m=n-1,x,y;
        int k=0;
        while((m&1)==0)
        {
            k++;
            m>>=1;
        }
        for(int i=0; i<Times; i++)
        {
            a=rand()%(n-1)+1;
            x=quick_mod(a,m,n);
            for(int j=0; j<k; j++)
            {
                y=multi(x,x,n);
                if(y==1&&x!=1&&x!=n-1) return false;
                x=y;
            }
            if(y!=1) return false;
        }
        return true;
    }
     
    LL Pollard_rho(LL n,LL c)
    {
        LL x,y,d,i=1,k=2;
        y=x=rand()%(n-1)+1;
        while(true)
        {
            i++;
            x=(multi(x,x,n)+c)%n;
            d=gcd((y-x+n)%n,n);
            if(1<d&&d<n) return d;
            if(y==x) return n;
            if(i==k)
            {
                y=x;
                k<<=1;
            }
        }
    }
     
    void find(LL n,int c)
    {
        if(n==1) return;
        if(Miller_Rabin(n))
        {
            fac[ct++]=n;
            return ;
        }
        LL p=n;
        LL k=c;
        while(p>=n) p=Pollard_rho(p,c--);
        find(p,k);
        find(n/p,k);
    }
     
    void dfs(LL dept, LL product=1)
    {
        if(dept==cnt)
        {
            arr[c++]=product;
            return;
        }
        for(int i=0; i<=num[dept]; i++)
        {
            dfs(dept+1,product);
            product*=fac[dept];
        }
    }
     
    void Solve(LL n)
    {
        ct=0;
        find(n,120);
        sort(fac,fac+ct);
        num[0]=1;
        int k=1;
        for(int i=1; i<ct; i++)
        {
            if(fac[i]==fac[i-1])
                ++num[k-1];
            else
            {
                num[k]=1;
                fac[k++]=fac[i];
            }
        }
        cnt=k;
    }
     
    const int M=1000005;
    bool prime[M];
    int p[M];
    int k1;
     
    void isprime()
    {
        k1=0;
        int i,j;
        memset(prime,true,sizeof(prime));
        for(i=2;i<M;i++)
        {
            if(prime[i])
            {
                p[k1++]=i;
                for(j=i+i;j<M;j+=i)
                {
                    prime[j]=false;
                }
            }
        }
    }
     
    int main()
    {
        LL n,t,record,tmp;
        isprime();
        while(cin>>n)
        {
            LL ans=-1;
            record=0;
            while(true)
            {
                tmp=1;
                if(Miller_Rabin(n))
                {
                    Solve(n-1);
                    c=0;
                    dfs(0,1);
                    sort(arr,arr+c);
                    bool flag=0;
                    for(int i=0; i<c; i++)
                    {
                        if(quick_mod(10,arr[i],n)==1)
                        {
                            tmp=arr[i];
                            break;
                        }
                        if(i==c-2) flag=1;
                    }
                    if(flag)
                    {
                        if(ans<tmp) record=n;
                        cout<<record<<endl;
                        break;
                    }
                }
                else
                {
                    bool flag=false;
                    LL tmp1=(LL)sqrt(n*1.0);
                    if(tmp1*tmp1==n&&Miller_Rabin(tmp1))
                    {
                        x=tmp1;
                        y=2;
                        flag=true;
                    }
                    else
                    {
                        LL cnt1=0,rea=n;
                        for(int i=0;i<k1;i++)
                        {
                            if(rea%p[i]==0)
                            {
                                x=p[i];
                                while(rea%p[i]==0)
                                {
                                    rea/=p[i];
                                    cnt1++;
                                }
                                break;
                            }
                        }
                        if(rea==1) flag=true;
                        y=cnt1;
                    }
                    if(flag)
                    {
                        Solve(x-1);
                        c=0;
                        dfs(0,1);
                        sort(arr,arr+c);
                        bool flag=0;
                        for(int i=0; i<c; i++)
                        {
                            if(quick_mod(10,arr[i],x)==1)
                            {
                                tmp=1;
                                for(int j=0; j<y-1; j++)
                                    tmp*=x;
                                tmp*=(x-1);
                                break;
                            }
                            if(i==c-2) flag=1;
                        }
                        if(flag)
                        {
                            if(ans<tmp)
                            {
                                ans=tmp;
                                record=n;
                            }
                        }
                    }
                }
                n--;
            }
        }
        return 0;
    }
  • 相关阅读:
    Java JDK和IntelliJ IDEA 配置及安装
    来吧学学.Net Core之登录认证与跨域资源使用
    来吧学学.Net Core之项目文件简介及配置文件与IOC的使用
    【转载】任正非:我的父亲母亲
    HTTP协议中的短轮询、长轮询、长连接和短连接
    跨域资源共享CORS详解
    C#各个版本中的新增特性详解
    仓央嘉措不负如来不负卿
    Redis Sentinel实现的机制与原理详解
    Redis的发布订阅及.NET客户端实现
  • 原文地址:https://www.cnblogs.com/topW2W/p/5456999.html
Copyright © 2020-2023  润新知