例题10-2 UVa12169 Disgruntled Judge(拓展欧几里德)

题意:

看白书

要点:

再一个办法就是枚举a,利用x1,x3求出b,判断所有x的关系能不能满足a,b。

如何通过a,x1,x3求出b呢。

x2 = (a * x1 + b) % 10001;
x3 = (a * x2 + b) % 10001;
联立2个式子
x3 = (a * (a * x1 + b) % 10001 + b ) % 10001;
x3 = (a * (a * x1 + b) + b) % 10001;
所以 x3 + 10001 * k = a * a * x1 + (a + 1) * b;
x3 - a * a * x1 = (a + 1) * b + 10001 * (-k);

这样就成了求 b 和 -k,满足这个式子,就是扩展欧几里得的一般用法

这是理论分析,然后实际做题中我WA了一次,TLE了一次,WA的原因是a我看错题了,题目中没有给定a的范围,我以为也是0~10000。TLE的原因是我一开始想直接用x[i]和x[I-2]判断b是否成立,感觉也没慢到那去,但就是TLE了,没办法只能按别人的来。


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ll long long
int x[500];

ll gcd(ll a, ll b, ll &x, ll &y)
{
	if (!b)
	{
		x = 1;	y = 0;
		return a;
	}
	ll ans=gcd(b, a%b, x, y);
	ll temp = x;
	x = y;
	y = temp - a / b*y;
	return ans;
}

int main()
{
	int n,i;
	ll a, t;
	scanf("%d", &n);
	for (i = 1; i <=2*n; i+=2)
		scanf("%d", &x[i]);
	ll xx, yy;
	for (a = 0;; a++)
	{		
		ll d = gcd(10001, -(a + 1), xx, yy);
		ll t = a*a*x[1] - x[3];
		if (t%d != 0)
			continue;		//不能整除直接无解
		yy *= t/d;
		bool flag = true;
		for (i = 2; i <= 2 * n; i++)
		{
			if (i & 1)		//同位与,相当与取奇数
			{
				if (x[i] != (a*x[i - 1] + yy) % 10001)
				{
					flag = false;
					break;
				}
			}
			else
				x[i] = (a*x[i - 1] + yy) % 10001;
		}
		if (flag)
			break;
	}
	for (i = 2; i <= 2*n; i+=2)
		printf("%lld\n",x[i]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值