修塔(gcd+裴蜀定理)

第3题     修塔 查看测评数据信息

有编号1~n 的n个塔,除了两个塔a和b 是好的不用修以外,其他都需要重修。

james和jordan展开修塔比赛,规则是轮流修,每次可以修第j+k或j-k号塔,其中j和k是已经修好的任意两个塔,

如果不能修塔,就输了。给出n,a,b,从 james开始,问最后谁赢了。

 

输入格式

 

第一行,一个整数T, 1<=T<=10000,表示有T组测试数据。

接下来T行,每行3个整数: n,a,b。2<a,b,n200000。a!=b。

 

 

 

 

输出格式

 

共T行,每行一个字符串。

 

 

输入/输出例子1

输入:

1

5 2 3

 

输出:

james

 

 

样例解释

 

问题分析:

分析一下,第一轮可能是a-b,a+b,b-a,b+a

第二轮可能是a-2b,2a-b,2a+b,2b+a,b-2a,2b-a,等等等等

我们发现这些数都是由 xa+yb组合而来的,很像线性组合,其中x,y为整数

考虑几个线性组合相加,ax1+by1+ax2+by2=a(x1+x2)+b(y2+y1),2个整数相加的结果也是整数

有可能得出7a+3b吗?可以的,比如a+a+...+a+b+b+b,7a-3b也都可以取到

但是1<= 7a+3b <=n 才可以取到。我们举例,4x+6y,结果一定是gcd(4,6)的倍数

一共有n/gcd(a,b)个塔,根据上面举例推广而来,这样就只要判断塔的奇偶性即可求出答案

如果能算出所有能修的塔的数量P,然后判断P的奇偶,P为奇数,就是先手 james赢,P为偶数就是后手jordan赢。

可以试试暴力计算P。先预处理出aba+ba-b2a+b2a-b,即可以修的塔的编号ab的线性组合,即ax+by,再判断这些塔号是否合法,判断时需要枚举工和y,复杂度为O(n^2)(也可以用宽搜)

下面用数论的办法直接得到P。根据裴蜀定理,ax + bygcd(a,b)的整数倍,也就是说,P是所有gcd(a,b)的倍数的个数,P = n/gcd(a,b)

 

以下是参考程序:

 

#include <bits/stdc++.h>
using namespace std;

int t, n, a, b;
int gcd(int a, int b)
{
	if (b==0) return a;
	return gcd(b, a%b);
}
int main()
{
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d%d", &n, &a, &b);
		if ((n/gcd(a, b))%2==0) printf("jordan\n");
		else printf("james\n");
	}
	return 0;
}

 

 

 

posted @ 2024-02-03 09:23  cn是大帅哥886  阅读(38)  评论(0)    收藏  举报