若是至少有一组解,则要 \(y\) 被 \(x\) 整除,也就是说 \(a_i\) 必定是 \(x\) 的倍数,可设 \(dp[i]\) 为 和为 \(i\) 且 \(gcd = 1\) 时的方案数,首先呢,若是不考虑 \(gcd\) 的限制,能够发现,\(dp[i]=1<<(i-1)\) ,那么咱们只要减去那些 \(gcd > 1\) 的方案数,枚举因子就行了,记忆化搜索便可。c++
#include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; long long p2(int x) { long long a = 1, k = 2; while (x) { if (x & 1) a = a * k % MOD; k = k * k % MOD; x >>= 1; } return a; } map<int, long long> dp; long long dfs(int x) { if (dp.count(x)) return dp[x]; long long res = p2(x - 1); for (int i = 1; i * i <= x; i++) { if (x % i == 0) { if (i != 1) { res = (res - dfs(x / i) + MOD) % MOD; } if(i * i != x) res = (res - dfs(i) + MOD) % MOD; } } return dp[x] = res; } int main() { dp[1] = 1; int x, y, n; long long ans = 0; cin >> x >> y; if (y % x == 0) { ans = dfs(y / x); } cout << ans << endl; return 0; }
\(dp[i]\) 表示从 \(i\) 开始(\(s[i...n-1]\))所能构成的不相交 \(t\) 串的最多个数,并维护最小花费 \(mn[i]\) 。spa
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; string s; int dp[N], mn[N], ab[N]; int main() { int n, m, k = 0; cin >> n >> s >> m; for (int i = n - 1; i >= 0; i--) { if(s[i] == '?') k++; if(s[i] == '?' || s[i] == 'a') { if(s[i + 1] == 'b' || s[i + 1] == '?') ab[i] = ab[i + 2] + 2; else ab[i] = 1; } if(n - i >= m) { dp[i] = dp[i + 1]; mn[i] = mn[i + 1]; if(ab[i] >= m) { if(dp[i + m] + 1 > dp[i]) { dp[i] = dp[i + m] + 1; mn[i] = mn[i + m] + k; } else if(dp[i + m] + 1 == dp[i]) { mn[i] = min(mn[i], mn[i + m] + k); } } if(s[i + m - 1] == '?') k--; } } cout << mn[0] << endl; return 0; }