交上去之前我自己觉得我都不对,没想到能AC,数据的话n最大为50,所以枚举4个数的最小公倍数不超时,求最大公越数方法是欧几里得法
int gcd(int a,int b){
return b == 0 ? a : gcd(b,a % b);
}
这题真是,无语=-=。。。。
#include<cstdio>
#include<cstring>
#define MAXD 50 + 5
#define MAX_SIZE 500000 + 10
#define Inf 1 << 30
int lcm[MAXD][MAXD];
int finally[MAX_SIZE];
int coin[MAXD];
int n,m;
int gcd(int a,int b){
return b == 0 ? a : gcd(b,a % b);
}
void Get_lcm(){
for(int i = 0; i < n ;i++)
for(int j = i + 1; j < n; j++){
lcm[i][j] = coin[i] * coin[j] / gcd(coin[i],coin[j]);
lcm[j][i] = lcm[i][j];
}
}
int main(){
while(scanf("%d%d",&n,&m)){
int cnt = 0;
if(!n && !m) break;
for(int i = 0; i < n ;i++)
scanf("%d",&coin[i]);/*输入第i个硬币的面值*/
Get_lcm();
for(int a = 0; a < n ;a ++)
for(int b = a + 1; b < n; b++)
for(int c = b + 1; c < n; c++)
for(int d = c + 1; d < n; d ++){
finally[cnt++] = lcm[a][b] * lcm[c][d] / gcd(lcm[a][b],lcm[c][d]);
finally[cnt++] = lcm[a][c] * lcm[b][d] / gcd(lcm[a][c],lcm[b][d]);
}
for(int cases = 0; cases < m ; cases ++){
int minx = Inf,miny = Inf;
int x,y,z,j,t;
scanf("%d",&z);
for(int i = 0; i < cnt ; i++){
t = z / finally[i];
if(z % finally[i] == 0){
x = z;
y = z;
break;
}
else {
int p = t * finally[i];
int q = (t + 1) * finally[i];
int a = z - p;
int b = q - z;
if(a < minx){
minx = a;
x = p;
}
if(b < miny){
miny = b;
y = q;
}
}
}
printf("%d %d\n",x,y);
}
}
return 0;
}