C2 - 3rd - C - Pagodas(博弈?) —— 合理地联系,推广,应用

这题看了别人的题解才知道真正意思,哈哈哈,忍不住分享一下我的理解方式: n个什么东西站立在牛头山和云台山之间的寺里(好像可以理解为雕像?)。n个雕像矗立在牛头山和云台山之间的寺里,然而随着时间流逝,只剩下标号为a,b的两座雕像仍然矗立。俩猴子,(...monk=monkey)叫Y..和I..决定重铸雕像群的辉煌。俩候轮流建雕像,Y..先来。每一轮每猴只能重建一座雕像,标号为i,而且在已有的雕像中,找两个标号为j,k,那么i = j + k或者 i = j - k。每个标号的雕像只能重建一次。轮到谁,谁不能建新雕像谁就输,也就是说谁建最后一座雕像谁就赢(当然这里第一个样例就给出了这种等价唯一的不妥之处)。

大佬的优雅翻译以及牛逼题解:传送门

解题为主嘛,虽然意思和意境有所偏差,但是题意基本get到了。初见这题,又是俩人掐架,又是俩人轮流一人先,不禁让我想起了前几天刚补的一道题:B2-B - Breaking Branches(博弈)

不禁惊呼一声,卧槽,真的好像。但是这题好像又更复杂,什么i = j - k || i = j + k,俩人又是每次都会做出最明智的选择(折树枝那个好像也有这句话),我现在(写这篇文)的理解就是做出最明智的选择 = 战满所有回合,所有的可能他俩都会涉及到。当时做这题的时候,有点懵,但是有了折树枝那题的先例,我就在想是不是只需要找出所有的修到标号的可能,然后再判断奇偶数就能得出答案了?大胆猜测,小心验证。我试了几个例子,好像是这么一回事。那么接下来的任务就是怎么找出所有可能修到的标号呢?还是看样例,慢慢地,矛头就指向一个东西——最大公约数。修的总数=原总数/gcd(a,b) - 2。当然我还是猜嘛,然后就代码实现。涉及到的知识点就是求俩数的最大公约数——辗转相除法。我就是笨比,场上其实不太会,还是搜的原理。。。然后感觉可以用递归写,但是又有点迷糊,就用while写的……代码敲完,一跑样例,全过。然后信心大增,就直接交了,直接过了。哈哈哈哈,心情贼爽!

场上写的码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;

int gcd(int a, int b) {
    int t;
    if(a < b)
        swap(a, b);
    while(a % b != 0) {
        t = a;
        a = b;
        b = t % b;
    }
    return b;
}
int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int a, b, t, n;
    int cnt = 0;
    cin >> t;
    while(t--) {
        cnt++;
        cin >> n >> a >> b;
        cout << "Case #" << cnt << ": ";
        if(((n/gcd(a,b))-2)%2)
            cout << "Yuwgna" << endl;
        else
            cout << "Iaka" << endl;
    }
//    cout << gcd(a, b);
    return 0;
}

然后我发现我写的gcd函数真就是原理直接照搬。。。

两个点:

1.其实不用判断大小关系,大不了就多进行一次循环的事;

2.想要的递归代码:

int gcd(int a,int b) {
	return b?gcd(b,a%b):a;
}

 换上程序能更简洁一些

附一些额外的东西:

1.这题规律的证明

2.裴蜀定理

3.递归函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值