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;
}


posted @ 2020-10-02 17:48  Hugh_Locke  阅读(142)  评论(0编辑  收藏  举报