/ Vijos / 题库 / Euler /

题解

5 条题解

  • 1
    @ 2017-04-30 14:13:22

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LF double
    #define LL long long
    #define min(a,b) ((a<b)?a:b)
    #define max(a,b) ((a>b)?a:b)
    #define fo(i,j,k) for(int i=j;i<=k;i++)
    #define fd(i,j,k) for(int i=j;i>=k;i--)
    using namespace std;
    int const MxCnt=1e4;
    LL Ans,Cnt,Pri[MxCnt+10];
    bool CPri(LL N){
    int Mx=sqrt(N);
    fo(i,2,Mx)if(N%i==0)return 0;
    return 1;
    }
    void Prep(LL N){
    Cnt=0;int Mx=sqrt(N);
    fo(i,1,Mx)if(N%i==0){
    if(CPri(i+1))Pri[++Cnt]=i+1;
    if(CPri(N/i+1))Pri[++Cnt]=N/i+1;
    }
    }
    bool Cmp(LL X,LL Y){return X>Y;}
    void Dfs(int Pos,LL Y,LL X){
    if(Y==1)Ans=min(Ans,X);
    if((Pos>Cnt)||(Y==1)||(X>Ans))return;
    for(LL i=Pri[Pos]-1;Y%i==0;i*=Pri[Pos])Dfs(Pos+1,Y/i,X/(Pri[Pos]-1)*Pri[Pos]);
    Dfs(Pos+1,Y,X);
    }
    int main(){
    //freopen("d.in","r",stdin);
    //freopen("d.out","w",stdout);
    int T;scanf("%d",&T);
    fo(cas,1,T){
    LL Y;scanf("%lld",&Y);
    Prep(Y);
    sort(Pri+1,Pri+Cnt+1,Cmp);
    Ans=(Y==1)?Y:Y*10;Dfs(1,Y,Y);
    printf("%lld\n",Ans);
    }
    return 0;
    }

  • 0
    @ 2019-05-26 20:02:06
    /*数论 
    可以先写个欧拉筛输出前50个phi(x)观察特点 
    比如计算phi(x)=8的最小的i,结果是15 
    考虑将x分解为p1^a1*p2^a2*...*pk^ak (唯一分解定理)
    则phi(x)=p1^(a1-1)(p1-1)*p2^(a2-1)(p2-1)*...*pn^(ak-1)(pk-1)=n 
    n也可以分解为p1^b1*p2^b2*...*pk^bk,那么x与n同阶且大小接近 
    用线性筛筛出sqrt(n)内的所有质数,然后暴力搜索答案,尝试用质因子凑出n */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 50005
    typedef long long ll;
    int n, prime[MAXN];
    bool isp[MAXN];
    ll ans; 
    void getprime(int a)
    {
        memset(isp, 1, sizeof(isp));
        for(int i = 2; i <= a; i++)
        {
            if(isp[i]) prime[++prime[0]] = i;
            for(int j = 1; j <= prime[0] && i * prime[j] <= a; j++)
            {
                isp[i * prime[j]] = 0;
                if(i % prime[j] == 0) break;
            }
        }
    }
    bool IsPrime(ll x)
    {
        if(x & 1 ^ 1) return false;
        for(int i = 2; i * i <= x; i++)
            if(x % i == 0) return false;
        return true;
    }
    void dfs(int num, int rem, ll res)//num表示当前考虑到第几个质数,rem记录n分解后的剩余,res记录结果 
    {
        if(rem == 1)  //递归出口  
        {
            ans = std::min(ans, res);
            return ;
        }
        if(rem > MAXN - 2 && IsPrime(rem + 1))  //处理较大的质因子,当x+1为质数时,最小的phi(x)就是x+1 
        {
            ans = std::min(ans, res * (rem + 1));
            //return ;
        }
        for(int i = num; i <= prime[0]; i++)
            if(rem % (prime[i] - 1) == 0)  //ans中可以有prime[i]这个质因子  
            {
                int newrem = rem / (prime[i] - 1);
                ll newres = res * prime[i];
                dfs(i + 1, newrem, newres);  //质因子prime[i]出现一次 
                while(newrem % prime[i] == 0)  //质因子prime[i]出现多次 
                {
                    newrem /= prime[i];
                    newres *= prime[i];
                    dfs(i + 1, newrem, newres); 
                } 
            }
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        getprime(MAXN-1);
        for(int i=1;i<=t;i++)
        {
            scanf("%d",&n);
            ans = 1LL<<32;
            dfs(1, n, 1);
            if(ans == 1LL<<32) printf("-1\n");
            else printf("%lld\n", ans);
        }
        return 0;
    } 
    
  • 0
    @ 2017-04-25 22:43:05

    打表的好题

  • 0
    @ 2016-02-18 10:59:37

    这个我也来

  • -2
    @ 2016-01-10 18:26:11

    虽然我没有AC但我来抢个沙发

  • 1

信息

ID
1862
难度
7
分类
(无)
标签
递交数
162
已通过
25
通过率
15%
被复制
2
上传者