洛谷 P4571 [JSOI2009]瓶子和燃料
Description
Solution
一道裴蜀定理应用的题目。
裴蜀定理: 一定存在一组整数解使得 \(ax + by = gcd(a, b)\) 成立。
这里不再证明了,感兴趣的同学可以自行百度。
再来看这道题,假设只有两个瓶子,里面有燃料,可以来回倒。
那么不就是 \(ax + by\) 的形式吗,那么最大的值就为 \(gcd(a, b)\)。
此时,原题就变成了给定 \(n\) 个数,从里面选出 \(k\) 个数,使得这 \(k\) 个数的 \(gcd\) 最大。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
const int N = 1e5 + 10;
int n, k, cnt;
int p[N];//记录这 n 个数中有哪些个不同的因数,一共有 cnt 个。
map <int, int> mp;//mp[x]: 表示含有因数 x 的数有多少个。
int main(){
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++){
int x;
scanf("%d", &x);
for(int j = 1; j * j <= x; j++){
if(x % j != 0) continue;
if(!mp[j]) p[++cnt] = j;//把因数存下来
mp[j]++;//包含因数 j 的数个数++
if(!mp[x / j]) p[++cnt] = x / j;//处理 x / j
if(j * j != x) mp[x / j]++;
}
}
int ans = 0;
for(int i = 1; i <= cnt; i++)
if(mp[p[i]] >= k)//包含因数 p[i] 的数个数 >= k 时,统计最大值
ans = max(ans, p[i]);
printf("%d\n", ans);
return 0;
}