C. The Meaningless Game(Codeforces Round #426 (Div. 2) C)

题目的意思是说,两个人刚刚开始游戏的时候的分数, 都是一分, 然后随机一个人的分数扩大k倍,另一个扩大k的平方倍, 问给你一组最后得分,问能不能通过游戏得到这样一组得分。(谁扩大k倍, 谁扩大k的平方倍,是可以自由选择的, k的值只要是自然数就行了)。
题目做法: 对输入的两个数a, b。求(a*b) 的1/3次方, 如果不能得到,就是不能得的输出“No”。否则在看开方得到的数,能不能同时被a和b整除, 如果可以就输出“Yes”,否则就是“No”。

如何证明呢? 其实也很简单,由于两边一个扩大k倍, 一个扩大k^2 倍, 所以对a*b来说一定扩大了,k^3倍,如果不满足就一定是“No”,但是满足了不一定是“Yes”, 比如这样2, 32,这两个数。所以再限制一下就可以了,可以证明的到:
设在第一个判定条件成立的情况下:a*b 可以化简成 k1^(3*n1) * k2(3*n2)……ki(3*ni)。这里k1, k2……ki为素数, ni为整数。 由于第一个判定条件成立,一定可以化简成这样的情况。在满足两边都能被整除的情况下,每边都有(k1^n1 * k2^n2 * k3^n3 * …… ki^ni)这样一组, 所以外面还剩下一组(k1^n1 * k2^n2 * k3^n3 * …… ki^ni)。为了方便证明我们现在只证明k1 是可以满足的,那么其余的也都可以满足。设a分的剩下n1个k1中的x个, 那么b分得了(n1-x) 个, 设在整个游戏中 对于a来说获得乘k^2的次数为m1次,获得乘k的次数为m2次那么,对于b就是反过来的。所以满足一下两个等式:
n1 + x - m1 * 2 - m2 == 0
n1 + n1 - x - m1 - 2 * m2 == 0
可以通过简单的化简,以上等式恒成立, 所以,无论x的值是多少,最后的结果都是对的。以上得证。

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <math.h>
using namespace std;
#define Max_N (1000000+100)
long long int a, b;
long long int c;
int n;
long long int k1;
long long int c1;
int main()
{   
    scanf("%d", &n);
    while (n--) {
        c1 = 0;
        scanf("%lld%lld", &a, &b);
        k1 = a*b;
        c = int(pow(k1, 1.0/3));//由于pow函数有精度误差所以下面做法可以消除这个。
        if (c * c * c == a*b) {
            c1 = c;
        }
        else if ((c-1) * (c-1) * (c-1) == a*b) c1 = c-1;
        else if ((c+1) * (c+1) * (c+1) == a*b) c1 = c+1;
        if (c1 == 0) {
            printf("No\n");
            continue;
        }
        else {
            if (a%c1 == 0 && b%c1 == 0)
                printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值