题目抽象:给你你一个整数数组,能否从中取出一些树,使得他们的和能被m整除。
分析:见代码注释。
1 #include2 #include 3 using namespace std; 4 const int MS = 1000005; 5 int n, m; 6 int cnt[MS], r[MS], tem[MS]; 7 int main() { 8 scanf("%d%d", &n, &m); 9 memset(cnt, 0, sizeof(cnt));10 for (int i = 0; i < n; i++) {11 scanf("%d", &r[i]);12 r[i] %= m;13 cnt[r[i]]++; // 统计不同余数的个数14 }15 memset(r, 0, sizeof(r)); //初始化余数i不能构成16 for (int i = 0; i < m; i++) {17 if (cnt[i] > 0) { //处理余数i18 int x = 1;19 while (cnt[i] > 0) {20 int y = x < cnt[i] ? x : cnt[i];21 cnt[i] -= y; 22 x *= 2; // 倍增算法处理。23 int z = (i * y) % m; // y个余数i构成余数z.24 for (int j = 0; j < m; j++) {25 if (r[j])26 tem[(j + z) % m] = 1; // 在余数j的基础上构成余数(j + z) %m27 }28 for (int j = 0; j < m; j++) {29 r[j] += tem[j]; // 更新能构成的余数30 tem[j] = 0;31 }32 r[z] = 1; //余数z能构成33 }34 if (r[0] > 0)35 break;36 }37 }38 if (r[0] > 0)39 printf("YES\n");40 else41 printf("NO\n");42 return 0;43 }