一道GCD LCM题目题解

题目描述:

第一行和第二行输入8个数字,对应每一位第二行都小于第一行,求最小的值 x x x x x x对第一行每一位取余后等于第二行 ( x 不 小 于 第 一 行 的 每 个 数 ) (x不小于第一行的每个数) (x)

题目分析:

首先有式子 x x x% a = b a=b a=b, x x x% c = d c=d c=d,先设第一个满足条件的 x x x x 1 x1 x1对于每个满足题意的 x x x,都有 x = n ∗ L C M ( a , c ) + x 1 x=n*LCM(a,c)+x1 x=nLCM(a,c)+x1 L C M ( a , c ) LCM(a,c) LCM(a,c) a a a c c c的最小公倍数,这点可以自行证明。此时令 m = L C M ( a , c ) m=LCM(a,c) m=LCM(a,c)

随后,若引入一个新的 e , f e,f e,f x x x% e = f e=f e=f,则 x x x要在满足 x = n ∗ L C M ( a , c ) + x 1 x=n*LCM(a,c)+x1 x=nLCM(a,c)+x1的情况下查找满足新式子的最小 x 2 x2 x2,随后更新 m m m,因为之后满足的 x x x x 2 x2 x2的差值又要满足被 a , c , e a,c,e a,c,e整除,因此就要将 m m m更新为 m = L C M ( m , e ) m = LCM(m,e) m=LCM(m,e),以此类推,求得最后一个满足的最小 x x x即为答案。

复杂度大概是ans除一个阶乘吧,不太好算,但是比暴力枚举快一些

代码:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<string.h>
#include<math.h>
typedef long long ll;

using namespace std;

int m, n;
struct P {
	int a, b;
}p[8];

bool cmp(P a, P b) {
	return a.a < b.a;
}

int gcd(int a, int b) {//gcd模板,求最大公约数
	return (b ? gcd(b, a % b) : a);
}

int lcm(int a, int b) {//根据gcd求最小公倍数
	return a / gcd(a, b) * b;
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);//c++操作,不用管他
	for (int i = 0; i < 8; i++) cin >> p[i].a;
	for (int i = 0; i < 8; i++) cin >> p[i].b;//两行输入
	m = p[0].a, n = p[0].b + p[0].a; int j;//初始化,此时m每次加第一个a,n为满足第一对的最小值
	for (int i = 1; i < 8; i++) {
		for (j = n; ; j += m) {//j被初始化为当前最小值每次加m
			if (j % p[i].a == p[i].b && j % p[i - 1].a == p[i - 1].b) {//判断成立,更新n和m,退出当前层循环
				n = j, m = lcm(m, p[i].a); break;
			}
		}
	}
	cout << n << endl;
	return 0;
}
/*
2 3 5 7 11 13 17 19
1 2 4 6 10 12 16 18
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值