洛谷P2737 [USACO4.1]麦香牛块Beef McNuggets(DP,裴蜀定理)

题目

https://www.luogu.com.cn/problem/P2737

思路

裴蜀定理:方程\(\sum_{i=1}^{n}k_ix_i=b\)有整数解当且仅当\(gcd(k_1,k_2,...,k_n)|b\)

不知道的同学可以做一下这题:【模板】裴蜀定理

证明:

必要性

设 \(gcd(k_1,k_2,...,k_n)=g\)(后面也用g表示),则 \(g|k1,g|k2....\),又\(b=\sum_{i=1}^{n}k_ix_i\),所以\(g|b\)。

充分性

先证方程\(\sum_{i=1}^{n}k_ix_i=g\)有解,当\(n=2\)时根据扩展欧几里得算法显然成立,利用数学归纳法,假设\(n=k\)时方程有解,那么\(n=k+1\)时:

\(k_1x_1+k_2x_2+....+k_nx_n+k_{n+1}x_{n+1}=gcd(k_{n+1},g)\),就要证存在\(x_{n+1}\) 使 \(k_{n+1}x_{n+1}+\lambda g=gcd(k_{n+1},g)\)

解释一下\(\lambda g\),这是说因为 \(k=n\) 时方程有解,所以我们将解中的每一个\(x\)变为原来的 \(\lambda\) 倍,就使得\(\sum_{i=1}^{n}k_ix_i=\lambda g\),其中 \(\lambda\) 是任意整数。

那么,改写一下 \(k=n+1\)时的方程 :\(ax+by=gcd(a,b)\),肯定有解。

所以方程\(\sum_{i=1}^{n}k_ix_i=g\)有解,又因为\(g|b\),所以我们将方程\(\sum_{i=1}^{n}k_ix_i=g\) 的解变为原来的\(\frac{b}{g}\)倍就可以了。

综上,裴蜀定理得证。

解决问题

分析一下,这道题就是要找一个最大的\(b\),使得方程 \(\sum_{i=1}^{n}k_ix_i=b\) 无自然数解

根据裴蜀定理,如果\(g>1\),可以找到一个任意大的\(b\)(\(g\nmid b\)),使该方程没有整数解,自然更没有自然数解了,输出"0"。

如果\(g=1\),方程一定存在整数解,且\(b\)足够大时,一定能通过解的调整使各个\(x\)都变为自然数,所以满足题意的 \(b\) 是有上界的。

我们关心的是这个上界是多少。我太弱了不会证,那就开个1e6的数组试试吧,接下来跑DP就完事了。

然后,过了。。。

代码

#include<cstdlib>
#include<algorithm>
using namespace std;
int dp[1000000],a[11];
int gcd(int x,int y){
    if(x<y) swap(x,y);
    if(!y) return x;
    return gcd(y,x%y);
}
int main(){
    int n,i,j,ans=0,g=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        g=gcd(g,a[i]);
    }
    dp[0]=1;
    for(i=1;i<=1000000;i++){
        for(j=1;j<=n;j++){
            if(i>=a[j])
                dp[i]|=dp[i-a[j]];
        }
        if(!dp[i]) ans=i;
    }
    if(g==1) printf("%d",ans);
    else printf("0");
    system("pause");
    return 0;
}

补充

如果想进一步看看上界的值怎么算的巨佬请移步rqy小姐姐的博客https://www.luogu.com.cn/blog/rqy/solution-p2737

上一篇:前端小姐姐私密社交网站信息丢失!原因竟是不经意间点开了一些网站


下一篇:正射投影Python