码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #520 (Div. 2) B. Math

时间:2018-11-19 23:05:24      阅读:388      评论:0      收藏:0      [点我收藏+]

标签:stream   printf   describe   display   answer   string   required   bool   style   

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。

由于可以乘以一个任意的数,所以我们是可以改变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

 

Codeforces Round #520 (Div. 2) B. Math

标签:stream   printf   describe   display   answer   string   required   bool   style   

原文地址:https://www.cnblogs.com/heyuhhh/p/9986311.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!