The Meaningless Game,算是思维吧。

题目直接链接

题意:

  某游戏规则:每次选定数字k(正整数),两人初始分数为1,获胜者分数乘k2,失败者分数成k,给你两个数字,判断是否可能是本游戏的两人的得分。

分析:

  为啥题意我不写判断两个数可不可以表示成a*a*b和a*b*b呢,因为这样我后面就没的写了。。。好的,那我们证明一下这两个的等价性:假设有n局游戏,每局的数字为k1。。。kn,然后A获胜的局数是

a1。。。ax,B获胜的局数是b1。。。by,那么A的分数:k(a1)*k(a1)*。。。*k(ax)*k(ax)*k(b1)*。。。*k(by),同样的,b的得分:k(a1)*。。。*k(ax)*k(b1)*k(b1)*。。。*k(by)*k(by)于是令a=k(a1)*。。。*k(ax),b=k(b1)*。。。*k(by),那么A的得分:a*a*b,B的得分a*b*b,然后再反过来证,如果AB的得分可以表示成a*a*b和a*b*b那么一定有可能,直接构造:就两局第一局分数为a,A赢,第二局分数为b,B赢。证完等价之后,我们考虑一下怎么判断能不能表示成a*a*b和a*b*b,其实我们可以直接求出a,b来。我们另A的分数是x,B的分数是y,那么gcd(x,y)=a*b*gcd(a,b)。x/gcd(x,y)=a/gcd(a,b);y/gcd(x,y)=b/gcd(a,b);令t1=gcd(a,b)*gcd(a,b)*gcd(a,b)=x/(x/gcd(x,y)*x/gcd(x,y)*y/gcd(x,y));

令t2=y/(x/gcd(x,y)*y/gcd(x,y)*y/gcd(x,y)),要满足t1=t2=k3(k为整数)即可。证明很简单,首先满足能表示成a*a*b和a*b*b一定能满足t1=t2=k3(k为整数)(这么推过来的),满足t1=t2=k3也一定满足可以表示成a*a*b和a*b*b(都把a,b找出来了,肯定没问题),那么就好办了。

  还有一个小小的问题,判断三次时最好不要从1到x二分,否则可能爆long long,如果不放心区间的话,判断时也不应写mid*mid*mid,总之要注意一些爆long long的地方。

代码:

#include <cstdio>
long long G(long long a,long long b){
    if(b==0)
        return a;
    return G(b,a%b);
}
int B(long long a){
    long long l=1,r=a;
    while(l<=r){
        long long mid=(l+r)/2;
        if(a%mid==0&&mid*mid==a/mid)
            return 0;
        else if(mid*mid<=a/mid)
            l=mid+1;
        else
            r=mid-1;
    }
    return 1;
}
int main(){
    int n;
    scanf("%d",&n);
    long long js1,js2;
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&js1,&js2);
        long long js=G(js1,js2);
        long long a=js1/js;
        long long b=js2/js;
        if(js1%(a*a*b)){
            printf("No\n");
            continue;
        }
        long long jsjs=js1/(a*a*b);
        if(B(jsjs))
            printf("No\n");
        else if(jsjs*a*b*b==js2)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wish-all-ac/p/12745102.html