题目大意:
给定三个整数 a b c
给三个数字任意一个 +1 或 -1 算一次操作
求最少的操作次数,使得 b%a==0 且 c%b==0
输出最少操作次数及操作后的 a b c
a,b,c<=10000 T<=100
解题思路:
首先想到找规律,可以分成12种情况,a不变bc变共4种,b不变ac变共4种,c不变ab变共4种
但是这里是基于一个假设,即三个数中至少有一个数固定不改变,作为求其他两个答案的基准
但事实上,这种假设不可行,反例有 11 21 41,最少执行三次,即每个数 -1 即可,但这种方案三个数都进行了改变
所以找规律这个基础的办法不可行
于是就想到了枚举,枚举所有满足题意的 a b c ,再通过与给定的 a b c 绝对值差之和取小来找答案
需要注意的是,虽然 a b c<=10000,但是可能移动后的答案会超出10000这个界限(当 abc 内存在一个质数时)
例如:1 137 10000
因为10001是137的倍数,所以答案为1 137 10001
此时c超出了10000的界限
例如:137 10000 10000
可得答案为137 10001 10001
此时b与c都超出了界限
(因为a总是小于等于b,a如果为一个大质数,要使b%a==0成立,改变a时又总满足a<=b,所以a保证在10000内)
值域质数对答案会造成多大的影响
这需要举很多质数例子去验证
保险起见我用了11000作为最终的bc枚举界限(保证别TLE啥都好)
这样的复杂度小于6e5
乘以最大T,最坏情况复杂度为O(6e7),满足题意
(93ms/2000ms)
#include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; void solve(){ int a,b,c,i,j,k,ans[4]={INF,0,0,0},d; cin>>a>>b>>c; if(b%a==0&&c%b==0){ cout<<"0 "<<a<<' '<<b<<' '<<c<<' '; return; }//特判 for(i=1;i<=10000;i++) for(j=i;j<=11000;j+=i) for(k=j;k<=11000;k+=j){ d=abs(a-i)+abs(b-j)+abs(c-k); if(d<ans[0]){ ans[0]=d; ans[1]=i; ans[2]=j; ans[3]=k; } } cout<<ans[0]<<' '<<ans[1]<<' '<<ans[2]<<' '<<ans[3]<<' '; } int main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int T;cin>>T;while(T--) solve(); return 0; }