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
  • 相关阅读:
    使用jQuery实现伪分页
    使用jQuery实现option的上移和下移
    理解Flux架构
    React 入门学习笔记1
    ES6新特性6:模块Module
    ES6新特性5:类(Class)和继承(Extends)
    ES6新特性4:字符串的扩展
    ES6新特性3:函数的扩展
    ES6新特性2:变量的解构赋值
    ES6新特性1:let和const
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/9986311.html
Copyright © 2011-2022 走看看