zoukankan      html  css  js  c++  java
  • Codeforces Round #520 (Div. 2) B. Math

    B. Math

    time limit per test:1 second
    memory limit per test:256 megabytes

    Description:

    JATC's math teacher always gives the class some interesting math problems so that they don't get bored. Today the problem is as follows. Given an integer n, you can perform the following operations zero or more times:

    • mul x: multiplies n by x (where x is an arbitrary positive integer).
    • sqrt: replaces nn with n−−√n (to apply this operation, n−−√n must be an integer).

    You can perform these operations as many times as you like. What is the minimum value of n, that can be achieved and what is the minimum number of operations, to achieve that minimum value?

    Apparently, no one in the class knows the answer to this problem, maybe you can help them?

    Input:

    The only line of the input contains a single integer nn (1n10^6,1≤n≤10^6) — the initial number.

    Output:

    Print two integers: the minimum integer n that can be achieved using the described operations and the minimum number of operations required.

    Sample Input:

    20

    Sample Output:

    10 2

    题意:

    对n可以进行开方以及乘以一个数这两种操作(无限次),求经过操作后最小的为多少。

    题解:

    唯一分解定理告诉我们,n可以分解成若干个质数的乘积,比如n=a1^p1*a2^p2*...*an^pn,其中a1,a2,.....,an为质数。

    由于可以乘以一个任意的数,所以我们是可以改变p1,p2..pn的值的。我们假定现在已经把指数变为可多次开方的形式,那么最小的n值就是a1*a2*...*an。

    现在主要问题是解决操作次数,我们设一个数t,t为2^t>=max(p1,p2,....,pn)的最小值,那么现在我们就可以进行t次开方。

    最后再判断一下乘法操作就可以了。

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    using namespace std;
    
    typedef long long LL ;
    const int N = 1e6+5;
    int tot,n;
    int u[N],prim[N],vis[N],a[N];
    
    int main(){
        scanf("%d",&n);
        for(int i=2;i<=sqrt(n);i++){ 
            for(int j=i*i;j<=n;j+=i){
                if(!vis[j]) vis[j]=1;
            }
        }
        for(int i=2;i<=n;i++) if(!vis[i]) prim[++tot]=i;
        int tmp = n,cnt=1;
        while(tmp>1){
            if(tmp%prim[cnt]==0){
                tmp/=prim[cnt];
                a[prim[cnt]]++;
            }else{
                cnt++;
            }
        }
        int maxn = 1;
        cnt=0;
        LL ans = 1,f = 1;
        bool flag=false;
        for(int i=2;i<=n;i++) if(a[i]){
            maxn=max(maxn,a[i]),ans*=i;
        }
        for(int i=2;i<=n;i++){
            if(a[i]&&a[i]!=maxn) flag=true ;
        }
        while(1){
            if(f>=maxn){
                if(flag) break ;
                if(f==maxn) flag=false;else flag=true;
                break;
            }
            f*=2;
            cnt++;
        }
        printf("%lld %d",ans,cnt+(flag==true));
        return 0;
    }
    View Code

    后来我看了一下其它人的代码,十分简洁,发现不用把素数给筛出来,具体代码可以看下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int n,cnt,ans=1;
    vector <int > vec ;
    
    int main(){
        scanf("%d",&n);
        int maxn = 0;
        for(int i=2;i<=n;i++){
            cnt = 0;
            if(n%i==0) ans*=i;
            while(n%i==0){
                n/=i;
                cnt++;
            }
            while(1<<(maxn)<cnt) maxn++;
            if(cnt) vec.push_back(cnt);
        }
        int flag = 0;
        for(int i=0;i<vec.size();i++){
            if(vec[i]!=(1<<maxn)) flag=1;
        }
        printf("%d %d",ans,flag+maxn);
        return 0;
    }
    View Code
  • 相关阅读:
    Squid-Squid 多层Cache 如何设置实现墙内直连,墙外域名走国外Proxy
    利用win2008虚拟化hyper-v 和squid反向代理,自己做个IDC
    再次分享 pyspider 爬虫框架
    刘宇:我如何5分钟拿到李书福的投资?
    刘宇:2014年投资感悟
    刘宇(正和磁系资本创始人)_百度百科
    python编写的自动获取代理IP列表的爬虫-chinaboywg-ChinaUnix博客
    采集爬虫中,解决网站限制IP的问题?
    Web 应用性能和压力测试工具 Gor
    dnspod-sr内网轻量级DNS首选方案
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/9986311.html
Copyright © 2011-2022 走看看