Pagodas HDU - 5512(好题,裴蜀定理,博弈)

题意:曾经在牛首山和云台山的中央,有 n 座古塔矗立在宏觉寺,从 1 标号至 n。然而只有其中的两座(标号为 a 与 b, 满足 1 <= a < b <= n)承受住了时间的考验。
有两个和尚,分别叫做 Yuwgna 和 Iaka,想让其重现佛光,便决定轮流修建古塔,Yuwgna 执先。对于每一个回合,其中一个人可以选择修建编号为 i (i∉{a,b},1 <= i <= n)的古塔,对于编号 i 应满足:设现有两古塔编号为 j 与 k ,则 i==j+k 或 i==j-k。每一座古塔不能建造两次。
视其为一个游戏,当某一个和尚不能再建造新塔时视为游戏失败,同样的,另一个和尚获得胜利。

题解:首先在数论中有一个基本性质:若a%g=0,b%g=0,则(x*a+b*y)%g=0(辗转相除法的基本原理)。所以本题中的j+k与j-k都是a,b最大公约数g的倍数,计算出可以放塔的数量,根据奇偶性输出答案。

em....后来又学了ex-gcd,发现这其实是一个裴蜀定理:对于任意的正整数a,b,一定存在非零整数x,y,使得x*a+y*b=gcd(a,b),且gcd(a,b)是给a添加一个系数x,给b添加一个系数y能凑出来的最小的正整数,所以对于任意的x*a+y*b=d,d一定是gcd(a,b)的倍数。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <algorithm>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int gcd(int a,int b) {
	return b?gcd(b,a%b):a;
}
main() {
	IOS;
	int t,kase=0;
	cin>>t;
	while(t--) {
		int n,a,b;
		cin>>n>>a>>b;
		printf("Case #%d: %s\n",++kase,n/gcd(a,b)%2==0?"Iaka":"Yuwgna");
		//printf("Case #%d: %s\n", ++kase, (n / gcd(a, b) % 2) ? "Yuwgna" : "Iaka");
	}
}

猜你喜欢

转载自blog.csdn.net/Alanrookie/article/details/107785097