CodeForces1311D 思维 + 二分
题意
给你三个整数a,b,c;
每一次操作你可以让三个其中之一 +1 或者 -1,你可以执行无限次这样的操作,但是你不能将他们变成非正数。
你需要找到最小操作数以至于b是a的倍数,c是b的倍数。
t组数据, 1<=t<=100
每组三个数a,b,c。(1<=a<=b<=c<=1e4).
题解
根据数据范围,可以想到去枚举其中的一个数,然后check其他两位数的最小符合限制的代价,思考之后发现枚举a,c都不容易,可以选择枚举b
先预处理出1 ~ 2e4中所有数字的倍数以及因数两个vector,然后枚举b的时候,用二分找出最小的满足a,c条件的数字
时间复杂度 NlogN
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fi first
#define se second
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define mp make_pair
const int maxn = 2e4 + 10;
const int INF = 0x3f3f3f3f;
int N,M,K;
vector<int>Q[maxn],P[maxn];
void init() {
for(int i = 1; i < maxn; i ++) {
for(int j = i ; j < maxn; j += i) {
Q[j].push_back(i);
P[i].push_back(j);
}
}
}
int main(){
int T; scanf("%d", &T);
init();
while(T--) {
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int ans = INF;
int A,B,C;
for(int i = 1; i <= 2e4; i ++) {
int tmp = abs(i - b);
if(tmp >= ans) continue;
int q = lower_bound(Q[i].begin(), Q[i].end(), a) - Q[i].begin();
if(q >= Q[i].size()) q--;
int x = abs(Q[i][q] - a);
if(q && abs(Q[i][q - 1] - a) < x) x = min(x, abs(Q[i][--q] - a));
tmp += x;
if(tmp >= ans) continue;
int p = lower_bound(P[i].begin(), P[i].end(), c) - P[i].begin();
if(p >= P[i].size()) p--;
x = abs(P[i][p] - c);
if(p && abs(P[i][p - 1] - c) < x) x = min(x, abs(P[i][--p] - c));
tmp += x;
if(tmp >= ans) continue;
ans = tmp;
A = Q[i][q],B = i,C = P[i][p];
}
cout << ans << endl;
cout << A << " " << B << " " << C << endl;
}
return 0;
}