持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路。
题目E1
题目E2
中文大意
给我们四个整数选择两个数 并且%E1和E2的差别就是a,b,c,d的范围不一样
E1解法
因为我们需要找到两个数但是由于数据范围所以我们先固定一个数然后去找另一个数。
为了让%我们可以想到如果是%是最好的,并且%这样我们就可以知道肯定是a*b的因数,所以这题我们就可以化简为一题求因数的题目。 所以在我们枚举x时我们找出这样其实我们就求出了一个S所以对于这个S我们也可以求出M,这样的话这样就可以保证我们现在的肯定是的倍数所以这样我们现在就可以求出最小M的整数倍是否在题目要求的范围内即可
void solve()
{
int a,b,c,d; cin >> a >> b >> c >> d;
int k = a * b;
for(int i = a + 1; i <= c;i++) {
int m = __gcd(k,i);
m = k / m;
int j = d / m * m;
if(j > b && j <= d) {
cout << i << ' ' << j << endl;
return;
}
}
cout << -1 << ' ' << -1 << endl;
}
E2解法
对于E2由于数的范围到了所以如果我们直接遍历的话是会超时的所有我们需要换一种写法。通过E1我们推导出了几个式子中得知我们可以先求出的因子然后我们可以先求出的最小整数倍然后求出的最小整数倍是否在数据范围内即可。但是我们发现如果是直接求的因数我们是会超时的,因为a和b的数据范围都到了1e9,然后我们可以想到一个数字的因子数其实是很小的,这样我们可以先分别求出a和b的因子数遍历组合数a*b的所有因子数
//先分别求出a,b的因子数
int n = 0, m = 0;
for(int i = 1; i * i <= a; i++) {
if(a % i == 0) {
x[++n] = i;
if(i * i != a) x[++n] = a / i;
}
}
for(int i = 1; i * i <= b; i++) {
if(b % i == 0) {
y[++m] = i;
if(i * i != b) y[++m] = b / i;
}
}
rep(i,n) rep(j,m) { //遍历组合出a*b的所有因子
int t = x[i] * y[j]; // a*b的因子
int k = a * b / t; //求出了 k = n * m
int l = ((a / t ) + 1)* t;//因为不可能等于本身所以加一
int r = ((b / k ) + 1)* k;
if(l > a && l <= c && r > b && r <= d) {
cout << l << ' ' << r << endl;
return;
}
}
cout << -1 << ' ' << -1 << endl;