Music Problem
题目链接:https://ac.nowcoder.com/acm/contest/5203
题意简化一下就是让我们在数组中找出一组子序列的和为3600的倍数
想法:
我们不妨考虑下 dp 的做法 (但是好像不是官方的正解)
我们设 dp[i] 代表 % 3600 之后结果为 i 的序列的个数
我们考虑转移方程
dp[(j + a[i]) % 3600] = dp[(j + a[i]) % 3600] + 1
但是要注意这里能转移过去的前提是序列的和可以为 j
#pragma GCC optimize(3,"Ofast","inline")//O3优化 #pragma GCC optimize(2)//O2优化 #include <algorithm> #include <string> #include <cstring> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <cmath> #include <cstdio> #include <iomanip> #include <ctime> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #define LL long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) const double eps = 1e-10; const int maxn = 1e5 + 10; const int mod = 10; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; int a[maxn],f[maxn],temp[maxn]; int main() { int T; cin >> T; while (T--) { int n; cin >> n; for (int i = 0;i <= 3600;i++) { f[i] = 0; temp[i] = 0; } for (int i = 1;i <= n;i++) cin >> a[i]; for (int i = 1;i <= n;i++) { for (int j = 0;j < 3600;j++) { if (j == 0 || temp[j] != 0) f[(j + a[i]) % 3600] = f[(j + a[i]) % 3600] + 1; if (f[0] > 0) { break; } } if (f[0] > 0) break; for (int j = 0;j < 3600;j++) temp[j] = f[j]; } if (f[0] > 0) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }