京电的碧绿航线

在京州电子科技大学,学生们做了一个游戏叫碧绿航线参加某青春比赛;这个游戏中,一艘船有六种属性:火力,航空,雷装,装填,航速,耐久。第i属性的周期分别为ai天,每艘船的每个属性在其周期中的某一天会达到顶峰。为了通关6-4来获得椿,我们需要这艘船在每个属性上都达到顶峰。我们记录了一艘船每个属性某次顶峰的时间为第bi天,我们想知道之后(如果今天就可以也算)第一个可能达到去6-4要求的时间为多少。其中ai互质

Input

第一行6个正整数表示ai(1≤ai≤20)
第二行6个整数表示bi(1≤bi≤1,000,000)

Output

输出一个整数表示答案

Sample Input
2 3 5 7 11 13
1 1 1 1 1 1
Sample Output
1


这题是一道关于中国剩余定理的模板题,相当于要找到一个数n,使n对1<=i<=6满足n % ai=bi,设n=n1+n2+n3+n4+n5+n6,其中ni满足ni % ai==bi,且对1<=j<=6,j!=i有ni%j==0,即ni是所有aj(j!=i)的公倍数,设M=a1*a2*a3*a4*a5*a6,因为ai两两互质,故M是其最小公倍数,则有ni是(M/ai)的倍数.

所以,现在有两个条件:

1.ni%ai==bi

2.ni%(M/ai)==0

又有,M/ai与ai互质,故gcd(M/ai,ai)=1,用扩展欧几里得算法e_gcd(M/ai,ai,x,y),有x*M/ai+y*ai=1 , 等式两边%ai,有:

   (x*M/ai)%ai=1

故(bi*x*M/ai)%ai==bi,且(bi*x*M/ai)%(M/ai)==0.

发现其满足条件1,2,故bi*x*M/ai就是我们要找的ni,即ni=bi*x*M/ai,最后n再n=n%M

本题有一个坑,就是n对任意1<=i<=6需要满足n>=bi,故设maxb为最大的一个bi,while(n<maxb)n+=M.


代码如下:

#include<iostream>
#include<algorithm>


using namespace std;
#include<string.h>

const int Max = 64000000;

bool flag1[Max];

long long gcd(long long a, long long b)
{
	if (b != 0)
		return gcd(b, a%b);
	else
		return a;
}

long long exGcd(long long a, long long b, long long &x, long long &y)
{
	if (b == 0)
	{
		x = 1; y = 0;
		return a;
	}
	long long r = exGcd(b, a%b, x, y);
	long long t = x; x = y; y = t - a / b*y;
	return r;
}





int main()
{
	long long ai[7];
	long long bi[7], lrm1[7], lrm2;
	long long i, maxb, j, k;
	while (scanf("%lld", &ai[1]) != EOF)
	{
		maxb = 0;
		for (i = 2; i <= 6; i++)
			scanf("%lld", &ai[i]);
		for (i = 1; i <= 6; i++)
		{
			scanf("%lld", &bi[i]);
			maxb = max(bi[i], maxb);
			bi[i] = bi[i] % ai[i];
			if (bi[i] == 0)
				bi[i] = ai[i];
		}

		lrm2 = 1;
		for (i = 1; i <= 6; i++)
			lrm2 *= ai[i];
		for (i = 1; i <= 6; i++)
			lrm1[i] = lrm2 / ai[i];

//		cout << lrm2 << endl;
		long long sum = 0;
		long long temp;
		for (i = 1; i <= 6; i++)
		{
			long long x, y;

			temp = lrm1[i];

			exGcd(lrm1[i], ai[i], x, y);

			temp *= x;

//			while (temp%ai[i] != bi[i])
//				temp += lrm1[i];

			temp *= bi[i];

			lrm1[i] = temp;
			sum += temp;
		}
		sum %= lrm2;
		if (sum == 0)
			sum = lrm2;
//		cout << sum << "  " << maxb << endl;
		temp = sum;
		while (temp < maxb)
		{
			temp += lrm2;
		}
		sum = temp;
		cout << sum << endl;
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值