CF 520 div.2 B. Math

题意:给定数n,可进行两种操作:乘一个任意数x; 开方,( sqrt(n)必须为整数

           输出可达最小值ans 及 最小操作数

  一个数可分解成有限个质数的幂次相乘:n=p1^x1 * p2^x2 * p3^x3...,  则n的所有质因子的乘积即为ans

  接下来就是找所有质因子和判断最小操作数了

  从 i=2 开始 n的第一个因子必为质数,不断除该因子,减小n, 新得到n的第一个因子也必为质数, 重复,直至 i==n

       咋找最小操作数捏,e.g.     40=2^3*5^1; ans=10, 能开方次数必为2的幂次, 这里幂次最大为3, 则要开方至少得*2得到2^4

  so 问题解决了 最小操作数就是开方次数+乘数的次数

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<list>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> p;
typedef long double ld;
#define mem(x) memset(x, 0, sizeof(x))
#define me(x) memset(x, -1, sizeof(x))
#define fo(i,n) for(i=0; i<n; i++)
#define sc(x) scanf("%lld", &x)
#define pr(x) printf("%lld
", x)
#define pri(x) printf("%lld ", x)
#define lowbit(x) x&-x
const ll MOD = 1e18 +7;
const ll N = 6e6 +5;
map<ll,ll>mp;
ll a[N];
int main()
{
    ll i, j ,k, l=0;
    ll n, m, t;
    cin>>n;
    if(n==1)
        return cout<<1<<' '<<0<<endl, 0;
    ll ans=1, mx=0, mi=MOD;
    m=0;
    for(i=2; i<=n; i++)
    {
        ll co=0;
        if(n%i==0) ans*=i;
        while(n%i==0)
            n/=i, co++;
        mx=max(co,mx);
        if(co)
        {
            mi=min(mi,co);
        }
        while((1<<m)<co) m++;

    }
    //cout<<"m="<<m<<" mx="<<mx<<" mi="<<mi<<endl;
    if(mi!=mx || (1<<m)!=mx) m++;
    cout<<ans<<' '<<m<<endl;
    return 0;
}
View Code

  

原文地址:https://www.cnblogs.com/op-z/p/10802757.html