1 条题解

  • 0
    @ 2025-4-8 21:04:56

    题意分析

    i从1到k,如果是素数,看2的i次方减1是否为合数,如果是,看是否能拆成几个素数相乘。

    解题思路

    用大整数因式分解Pollard_rho算法和大整数素数判断miller_rabin。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <map>
    using namespace std;
    #define ll long long
    bool prim[65];
    int p[65];
    int cnt;
    ll yz[111111];
    void init()
    {
        memset(prim,true,sizeof(prim));
        cnt=0;
        for(int i=2;i<64;i++)
        {
            if(prim[i])
            {
                p[cnt++]=i;
                for(int j=i*2;j<64;j+=i)
                    prim[j]=false;
            }
        }
    }
    ll mul(ll x,ll y,ll mod)
    {
        ll ans=0;
        while(y)
        {
            if(y&1)ans=(ans+x)%mod;
            x=(x+x)%mod;
            y>>=1;
        }
        return ans;
    }
    ll poww(ll x,ll y,ll mod)
    {
        ll ans=1;
        while(y)
        {
            if(y&1)ans=mul(ans,x,mod);
            x=mul(x,x,mod);
            y>>=1;
        }
        return ans;
    }
    bool miller_rabin(ll n)
    {
        ll t,u,a,x,y;
        if(n==2)return true;
        if(n==1||!(n&1))return false;
        for(t=0,u=n-1;!(u&1);t++,u>>=1);
        for(int i=0;i<10;i++)
        {
            ll a=rand()%(n-1)+1;
            x=poww(a,u,n);
            for(int j=0;j<t;j++)
            {
                y=mul(x,x,n);
                if(y==1&&x!=1&&x!=n-1)
                    return false;
                x=y;
            }
            if(x!=1)
                return false;
        }
        return true;
    }
    ll gcd(ll a,ll b)
    {
       if(a<0)
            return gcd(-a,b);
            if(a==0)
                return 1;
        while(b)
        {
            long long int t=a%b;
            a=b;
            b=t;
        }
        return a;
    }
    int num;
    ll Pollard_rho(ll n,ll c)
    {
        int i=1,k=2;
        ll x=rand()%(n-1)+1;
        ll y=x;
        while(1)
        {
            i++;
            x=(mul(x,x,n)+c)%n;
            ll p=gcd(y-x,n);
            if(p!=1&&p!=n)
                return p;
            if(y==x)
                return n;
            if(i==k)
            {
                y=x;
                k+=k;
            }
        }
    }
    void findx(ll n)
    {
        if(n==1)return;
        if(miller_rabin(n))
        {
            yz[num++]=n;
            //cout<<n<<endl;
            return ;
        }
        ll p=n;
        while(p>=n)
            p=Pollard_rho(p,rand()%(n-1)+1);
        findx(p);
        findx(n/p);
    }
    int main()
    {
       init();
       int k;
       //ll z=2047;
      // findx(z);
       while(~scanf("%d",&k))
       {
            for(int i=0;i<cnt;i++)
            {
     
                if(p[i]<k)
                {
                    ll kk=(1ll<<p[i])-1;
                   // cout<<p[i]<<' '<<kk<<endl;
                    if(!miller_rabin(kk))
                    {
                        //cout<<kk<<' ';
                        num=0;
                        findx(kk);
                        sort(yz,yz+num);
                        int ss=0;
                        printf("%lld",yz[0]);
                        for(int j=1;j<num;j++)
                        {
     
                            printf(" * %lld",yz[j]);
                        }
                        printf(" = %lld = ( 2 ^ %d ) - 1\n",kk,p[i]);
                    }
                }
            }
       }
       return 0;
    }
    
    • 1

    信息

    ID
    1193
    时间
    3000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    4
    已通过
    1
    上传者