CF833A The Meaningless Game 数学

分析

这道题有一点点数学的感觉(其实我只是看到了平方),来分析一下,两个人的初始值都一样,只知道最后的结果,中间的过程我们是不知道的,但可以很明显的看出,只要我的操作合法,两个数的乘积就一共扩大了\(k^3\)倍,所以关键的就是确定这个\(k\)是啥。
直接枚举是显然不可以的,需要找一些共性的东西,于是就想到了分解质因数。只要我分解出来的每个质因数,第一个数的个数和第二个数的个数加起来一定是3的倍数。因为\(k\)可以分解为\(p_1,p_2……p_n\)\(k^2\)就是把每个质因数都平方,所以一次操作就相当于多了3,说的可能绕了一些,反正就是这样。
这么写的正确性肯定是毋庸置疑的,但时间消耗会很大,尤其是涉及到取%的操作很多,于是就TLE了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int prime[N];
bool isp[N];
void init(){
    memset(isp,1,sizeof(isp));
    for(int i=2;i<=N-5;i++){
        if(isp[i])
            prime[++prime[0]]=i;
        for(int j=1;j<=prime[0]&&i*prime[j]<=N-5;j++){
            isp[i*prime[j]]=0;
            if(i%isp[j]==0)break;
        }
    }
}
int num[N],cnt[N];
int prim(int n){
    int mx=0;
    memset(num,0,sizeof(num));
    for(int i=1;prime[i]<=n&&i<=prime[0];i++){
        while(n%prime[i]==0){
            n/=prime[i];
            num[prime[i]]++;
            mx=i;
        }
    }
    return mx;
}
int prim_(int n){
    int mx=0;
    memset(cnt,0,sizeof(cnt));
    for(int i=1;prime[i]<=n&&i<=prime[0];i++){
        while(n%prime[i]==0){
            n/=prime[i];
            cnt[prime[i]]++;
            //printf("%d\n",prime[i]);
            mx=i;
        }
    }
    return mx;
}
int main(){
    int T;
    scanf("%d",&T);
    init();
    while(T--){
        int a,b;
        scanf("%d%d",&a,&b);
        if(a==1||b==1){
            printf("Yes\n");
            continue;
        }
        int pa=prim(a),pb=prim_(b);
        if(pa==0||pb==0||pa!=pb){
            printf("No\n");
        }
        else {
            bool ok=1;
            for(int i=1;i<=pb;i++){
                if((num[prime[i]]+cnt[prime[i]])%3!=0){
                    ok=0;break;
                }
            }
            if(ok)printf("Yes\n");
            else printf("No\n");
        }
    }
}

再想一下优化,其实没必要把每个质因数都枚举一遍,因为它又没让求是怎么分解的,所以直接对所有的整体的开三次方就好,然后这样就相当于开出了所有的质因数,先判断能不能开尽,再判断质因数就好。

#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e6+10;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int a,b;
        scanf("%d%d",&a,&b);
        ll s=(long long)a*b;
        ll x=pow(s,1.0/3)+0.5;
        if(x*x*x!=s||a%x||b%x)
            printf("No\n");
        else printf("Yes\n");
    }
}
posted @ 2020-04-22 06:04  An_Fly  阅读(96)  评论(0编辑  收藏  举报