题目链接:http://codeforces.com/contest/1062/problem/B
题目大意:给你一个数n
你可以有两种操作
操作1:n等于n乘以一个正整数x
操作2:n=sqrt(n) 但是sqrt(n)必须为整数

问你n最后得到的最小值是多少?及其需要操作的最小步数

20*5=100, sqrt(100)=10

最小值为10, 操作步数为2

思路:
假如n能得到的最小值为a;

那么n · x一定是a的偶数次幂,n=a · a · a · a·…。2的幂次方个a相乘

那么把a分解质因数a=a1 · a2 · a3 · a4 · a5 · …。

那么n= 2的幂次方个a1 · 2的幂次方个a2 · 2的幂次方个 a3 ·…。

最小值就是a1 · a2 · a3 · a4 · a5 · …。

那么只要把n分解质因数,再找到出现次数多的质因数,那么次数就是
ceil(log2(m))+1

举例:n=48=2 · 2 · 2 · 3 · 3
m=3

所以:只能把n凑成 2 · 2 · 2 · 2 · 3 · 3 · 3 · 3 那么x=2 · 3 · 3=18
sqrt(n) = 2 · 2 · 3 · 3
sqrt(n) = 2 · 3
一共3步

因为n*x为第一步
后面开方的步数为ceil(log2(m))

所以总共的步数为 ceil(log2(m))+1
m=出现次数最多的质因数的次数

当然如果m=1,那么就已经是最小的值,0 步。

我这里优化了一下,如果sqrt(n)==整数,那么就n=sqrt(n),一直处理到sqrt(n)!=整数。再进行上面的操作。

思考:第一次遇到分解质因数的题,很有意思

#include<bits/stdc++.h>

using namespace std;

int a[1000005];

int sq(long long n)//判断sqrt(n)是否为整数
{
    if(sqrt(n)-(long long)sqrt(n)<1e-6)
        return 1;
    else
        return 0;
}

long long p=0;
int Solve(long long n, long long &m)
{
    for(long long i=2; i*i<=n; i++)//分解质因数
    {
        while(n%i==0)
        {
            p=max(p, i);
            n/=i;
            a[i]++;
        }
    }
    if(n!=1)//判断是否是最后的质因数
    {
        p=max(p, n);
        a[n]++;
    }
    
    int s=1;
    for(int i=2;i<=p;i++)//计算最小值
    {
        if(a[i]!=0)
            s*=i;
    }
    
    /*计算次数*/
    m=*max_element(a, a+p+1);
    if(m==1)
        m=0;
    else
        m=ceil(log2(m))+1;

    return s;

}


int main()
{
    fill(a, a+1000005, 0);
    long long n, m, s=0;
    scanf("%lld",&n);
    if(n==1)
    {
        cout<<1<<' '<<0<<endl;
        return 0;
    }
    while(sq(n)&&n!=1)//处理sqrt(n)为整数
    {
        n=sqrt(n);
        s++;
    }
    int sum=Solve(n, m);
    cout<<sum<<' '<<m+s<<endl;


    return 0;
}