蓝桥杯 包子凑数(完全背包、裴蜀定理、赛瓦维斯特定理)

一、题目来源

OJ传送门

参考题解

赛瓦维斯特定理

2017年蓝桥杯软件类省赛C++语言大学A组第8题"包子凑数",一道数论题。

2022年4月青少年蓝桥杯赛第二次省赛初级+中高级组第三题

这也太tm内卷了,拿这个来考三年级的小孩子!真是太BT了!还第三题!!!

二、解题思路

  • 裴蜀定理
    简单来说,我们设 d=gcd(a,b),那么对于方程ax+by=d,一定存在一组整数解。并且对于方程 ax+by=z,如果满足 dz,那么方程一定有整数解,否则无整数解。

根据裴蜀定理,当所有种类的蒸笼包子数的最大公约数不为1时,凑不出的包子数为无限多,因为无论蒸笼怎么组合都必须得是gcd得倍数,gcd不为1一定会有凑不出的。

三、实现代码

#include <bits/stdc++.h>
using namespace std;
/**
 测试用例
 2
 3 5

 答案
 4
 */
typedef long long LL;
const int N = 1e6 + 5;

LL f[N];  //表示凑出j个包子的方法总数
int a[N]; //每种规格中包子的数量
int ans;  //组装不出来的包子个数

//最大公约数,辗转相除法
int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];

    //赛瓦维斯特定理 :  两个互质数a,b表示不出来的最大数字是 a∗b−a−b
    //下面排序后找出极小值与次小值,它们的乘积再减去极小和次小,就是极限值
    sort(a + 1, a + 1 + n);
    int m1 = a[1], m2 = a[2]; //最小和次小
    int M = m1 * m2 - m1 - m2;

    //求出所有数字的最大公约数
    int g = a[1];
    for (int i = 2; i <= n; i++) g = gcd(g, a[i]);

    /*裴蜀定理:如果所有数字的最大公约数大于1,那么必然存在无法表示出的数字。
     不互质栗子:
     比如3 和 6      两种规格,能组装的就是 3,6,9,12,15,这个变化就是它们的最大公约数3。
     比如3 和 6 和 9 三种规格, 能组装的也是 3,6,9,12,15,这个变化就是它们的最大公约数3。
     此时 ,类似于 1,2,4,5,7,...之类的数字均是无法凑出的,有无穷多个。

     互质栗子:
     比如 3 和  4   两种规格, 能组装的就是 3,4,6,7,8,9,10,11,12...., 根据赛瓦维斯特定理,我们知道,最大的不能组装的数字是3*4-3-4=5
     比如 3 和  4 和 6 三种规格,因为3,4就能组装出5以上的所有数字,所以我们只需要从最小a[1]到 M 中查找即可。
    */
    if (g > 1) {
        cout << "INF" << endl; // cout << -1 << endl; //青少组要求输出-1
        return 0;
    }

    /**
      完全背包
      f[j]表示凑出j个包子的方法总数,简单说就是如果f[j]>0就凑得出,f[j]=0就凑不出。
      递推式 f[j]=f[j−第i种蒸笼包子数]+1 (f[j−第i种蒸笼包子数]>=1)
      当j−第i种蒸笼包子数是可以凑成的,那么只需对其+第i种蒸笼包子数就可以凑成j个包子数。
     */
    f[0] = 1; //  0个包子这个状态是合法的,是可以到达的状态。而且只能是一种方案,就是不管是哪种规格,一概不要
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= M; j++)
            if (j >= a[i] && f[j - a[i]]) f[j]++;

    //枚举每个可能的数字,如果这个数字存在1种以上的方案,就是可以凑出,否则就是无法凑出
    for (int i = 1; i <= M; i++)
        if (!f[i]) ans++;

    //输出答案
    cout << ans << endl;
    return 0;
}
  • 赛瓦维斯特定理
    如果能够凑出的数有限,那么到达某个界限后都是凑得出的,这个界限为abab。这里由于有多个数字,我们可以采用最大做为a,次大做为b来求解。

  • 递推关系
    dp[i]表示凑出i个包子的方法总数,简单说就是如果其>=1就凑得出,==0就凑不出。

状态转移方程: dp[i]=dp[ij种蒸笼包子数]+1 (dp[ij种蒸笼包子数]>=1)
ij种蒸笼包子数是可以凑成的,那么只需对其+第j种蒸笼包子数就可以凑成i个包子数。

posted @   糖豆爸爸  阅读(297)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2021-04-23 集合专题
2019-04-23 网络安装Centos x64 6.10
2019-04-23 给没有连接因特网的centos使用yum安装其他软件。
2018-04-23 python强大的数据类型转换
2018-04-23 宁波智慧教育云平台
2015-04-23 开平区教育局资源分布式存储解决方案
2013-04-23 Windows版Mysql5.6.11的安装与配置
Live2D
点击右上角即可分享
微信分享提示