题目大意 : 给出一行数 从中任选几个数成为一个字区间 如果存在一个这样的区间和 能够整除 m时 输出YES 否则输出NO
解题思路 : 任选数构成子序列 不能用指针查找法来做了 本题考虑DP 本题所设计的状态是前个数所能构成的子区间里是否有满足条件的
如果前 i -1 里已经有满足条件的 那 前 i 也就一定有了 如果前 i - 1 没有那就要看是否有能与当下把b[i] 组成 % m == 0 的
#include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; const int MaxN = 1e6, MN = 1e3; int m, n, a[MaxN + 5], b[MaxN + 5]; bool f[MN + 5][MN + 5]; int main() { scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); if(n >= m) printf("YES\n"); //如果是这样 那么肯定有 s[i] & m == s[j] % m 而s[j] - s[i] == m 所以一定存在这样的s[i] 能够 % m == 0 else { for(int i = 1; i <= n; i++) { b[i] = a[i] % m; // 转为a[i] 在m下的剩余系 } for(int i = 1; i <= n; i++) { f[i][b[i]] = 1; for(int j = 0; j <= m - 1; j++) { if(j != b[i]) { f[i][j] = f[i - 1][j] || f[i - 1][(j - b[i] + m) % m]; // 注意这个转移方程 这是一个 || 运算 } } } if(f[n][0]) printf("YES\n"); else printf("NO\n"); } }
时间: 2024-10-10 10:34:29