1 条题解
-
0
自动搬运
来自洛谷,原作者为

Yxa_Sheep
打表过样例,暴力出奇迹,搜索真牛逼,骗分进省一||深搜 MLE,广搜 TLE,打表 RE,退火又 CE||删掉 display 看主页||被封取关(解封后私信)||六年级蒟蒻 ,代词请用“他”||当前状态:<离线>搬运于
2025-08-24 21:18:23,当前版本为作者最后更新于2025-07-20 17:40:10,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
给定 个数,每个数可以用无限次。求无法组成的数有多少个,如果有无限个就输出 。
思路
做题先看标签:动态规划+数论。在脑子里面规划一下,输出 用数论,输出正常答案用动规。
至于 怎么判,相信大家都有思路了。如果这 个数不互质(最小公因数不等于 ),那么就输出 。为什么呢?假设这 个数的最小公因数为 ,那么必须是 的倍数才能被这 个数组合出来。举个栗子, 和 这两个数的最小公因数是 ,必须是 的倍数的数才有可能被组合出来。
接下来是输出正常答案了。我们先设定状态, 表示能否组合出 。状态转移方程很好推,我们设输入的长度为 的序列叫 ,枚举一个 ,如果 的话那么 ,反之则为 。但是我们要到什么时候结束呢?设序列 中的最小值为 ,则在出现连续 次为 为 的时候退出。由于不确定长度,我们可以用 vector 存下 数组。这里注意肯定可以凑出 个汤圆,所以 ,可以在最开头这样写f.push_back(1)。更具体的实现方法见代码。代码
#include <bits/stdc++.h> using namespace std; int n, g, cnt, ans, a[30]; vector<bool> f; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), g = __gcd(g, a[i]); if (g != 1) { printf("-1"); return 0; } sort(a + 1, a + n + 1), f.push_back(1); for (int i = 1; cnt < a[1]; i++) { bool flag = 0; for (int j = 1; j <= n && a[j] <= i; j++) if (f[i - a[j]]) { flag = 1; break; } f.push_back(flag); if (flag) cnt++; else cnt = 0, ans++; } printf("%d", ans); return 0; }题解来之不易,且看且珍惜。给个赞再走吧。
题目传送门
- 1
信息
- ID
- 11874
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者