zoukankan      html  css  js  c++  java
  • 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
    ",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
    ");
                continue;
            }
            int pa=prim(a),pb=prim_(b);
            if(pa==0||pb==0||pa!=pb){
                printf("No
    ");
            }
            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
    ");
                else printf("No
    ");
            }
        }
    }
    

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

    #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
    ");
            else printf("Yes
    ");
        }
    }
    
  • 相关阅读:
    JAVA---File递归遍历文件目录,输出绝对路径
    JAVA--Map集合
    (笔记)JAVA--集合实现斗地主洗牌、发牌、看牌(利用TreeSet排序)
    SVN简单使用
    System.Object
    动态创建控件
    select 查询
    数据类型
    入门(值得注意的地方)
    错误调式 异常处理
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12748864.html
Copyright © 2011-2022 走看看