Luogu4571 [JSOI2009]瓶子和燃料(裴蜀定理)题解

前置芝士

裴蜀定理

\(a\)\(b\)是整数,且\(gcd(a,b)=d\),那么对于任意的整数\(x\)\(y\)\(ax+by\)都一定是\(d\)的倍数,特别地,一定存在整数\(x\)\(y\),使\(ax+by=d\)成立。

推广: \(a_1,a_2,a_3...a_n\)\(n\)个整数,\(d\)是它们的最大公约数,那么存在整数\(x_1...x_n\)使得\(x_1\times a_1+x_2\times a_2+...x_n\times a_n=d\)

思路

根据裴蜀定理,外星人所给出的燃料数量为\(k\)个瓶子容积的\(gcd\)。因此问题就转化为:从\(n\)个数中选出\(k\)个数,使得它们的\(gcd\)最大。

我们可以将每个数的因数分解出来(并不只是质因数),记录每一个因子的出现次数,排序以后选出最大的出现次数\(\geq k\)的就可以了。

另外,本题数值较大,需要开\(map\)

参考代码

#include <cstdio>
#include <algorithm>
#include <map>

using namespace std;

const int maxn = 1e6 + 10;
int n,cnt,k;
struct Num{
    int val,num;
}p[maxn];
map<int,int> T;

bool cmp(Num x, Num y){return x.val > y.val;}

int main(){
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++ i){
        int v; scanf("%d", &v);
        for(int j = 1; j * j <= v; ++ j){
            if(v % j == 0){
                if(!T[j]) T[j] = ++ cnt, p[cnt].val = j, p[cnt].num ++;
                else p[T[j]].num ++;
                int fff = v / j;
                if(fff == j) continue;
                if(!T[fff]) T[fff] = ++ cnt, p[cnt].val = fff, p[cnt].num ++;
                else p[T[fff]].num ++;
            }
        }
    }
    sort(p + 1, p + 1 + cnt, cmp);
    for(int i = 1; i <= cnt; ++ i)
        if(p[i].num >= k) return printf("%d\n", p[i].val), 0;
    return 0;
}
posted @ 2020-11-15 21:15  When_C  阅读(84)  评论(0编辑  收藏  举报