1226. 包子凑数

题目链接

1226. 包子凑数

给出 \(N\) 个数 \(A_i\),求有多少个数不能通过这些数凑出

输入格式

第一行包含一个整数 \(N\)

接下来 \(N\) 行,每行包含一个整数 \(A_i\)

输出格式

输出一个整数代表答案。

如果凑不出的数目有无限多个,输出INF。

数据范围

\(1≤N≤100,\)
\(1≤A_i≤100\)

输入样例1:

2
4
5

输出样例1:

6

输入样例2:

2
4
6

输出样例2:

INF

样例解释

对于样例1,凑不出的数目包括:\(1, 2, 3, 6, 7, 11\)
对于样例2,所有奇数都凑不出来,所以有无限多个。

解题思路

数论,完全背包变形
结论:对于两个互斥的数 \(a,b\),其不能凑出的最大的数为 \((a-1)\times (b-1)-1\)

\(99\)\(98\)\(100\) 内最大的互斥的两个数可以考虑最大的数取 \(10000\),由于再有更多的数的话可选择的数更多,最大的数可能还不止\(10000\),同时,如果 \(n\) 个的数的最大公约数不为 \(1\),则其凑不出来的数有无限个,因为这些数可以约数不为该最大公约数
\(\color{red}{如果 n 中不存在两个互斥的数呢?}\),在 \(100\) 范围内这样的情况很难出现,且题目应该是保证有解的,所以这种情况可以忽略

下面的问题就变成了完全背包问题:

  • 状态表示:\(f[i][j]\) 表示前 \(i\) 个数是否可以凑出 \(j\)

  • 状态计算:\(f[i][j]=f[i-1][j]\,||\,f[i][j-a[i]]\)

  • 时间复杂度:\(O(10000\times n)\)

代码

// Problem: 包子凑数
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1228/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=105;
int n,a[N];
bool f[N][N*N];
int main()
{
    cin>>n;
    int d=0;
    for(int i=1;i<=n;i++)
    {
    	cin>>a[i];
    	d=__gcd(d,a[i]);
    }
    if(d!=1)puts("INF");
    else
    {
    	f[0][0]=true;
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<N*N;j++)
    		{
    			f[i][j]|=f[i-1][j];
    			if(j>=a[i])f[i][j]|=f[i][j-a[i]];
    		}
    	int res=0;
    	for(int i=0;i<N*N;i++)res+=!f[n][i];
    	cout<<res;
    }
    return 0;
}
posted @ 2022-02-17 17:09  zyy2001  阅读(75)  评论(0)    收藏  举报