标签:
题目链接:http://codeforces.com/problemset/problem/577/B
题目意思:就是给出 n 个数(a1, a2, ..., an) 和 m,问能不能从这 n 个数中选出一些数(不能为空),使得这些数的总和能整除 m 。
实不相瞒,完全没想法。。。看题解,有个地方看都看不懂: n > m的情况。求助乌冬子,连带被批英语水皮 >___<。还是谢谢他啦,一步一步引导我。
貌似挺多人也有这个疑惑的。他说那个是特例优化,原谅我懒,直接摘抄吧~
首先知道一些参数。 前缀和 Sl = a1 + a2 + ... + al-1 + al;Sr = a1 + a2 + ... + al-1 + al + al+1 + ... + ar-1 + ar; Sr - Sl = al+1 + al+2 + ...ar-1 + ar
那个翻译就是,如果有两个前缀和 mod m 相等(Sr = Sl(mod m) ),那么就有以下的前缀和向区间和的转化了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <set> 6 using namespace std; 7 8 int main() { 9 #ifndef ONLINE_JUDGE 10 freopen("in.txt", "r", stdin); 11 #endif // ONLINE_JUDGE 12 13 int n, m; 14 while (scanf("%d%d", &n, &m) != EOF) { 15 16 int a, r; 17 set<int> mods; 18 set<int> mods_tmp; 19 20 mods.insert(0); 21 for (int i = 0; i < n; i++) { 22 scanf("%d", &a); 23 for (set<int>::iterator it = mods.begin(); it != mods.end(); ++it) { 24 int r = (*it + a) % m; 25 if (r == 0) { 26 printf("YES\n"); 27 return 0; 28 } 29 mods_tmp.insert(r); 30 mods_tmp.insert(a); 31 } 32 mods.insert(mods_tmp.begin(), mods_tmp.end()); 33 mods_tmp.clear(); 34 } 35 printf("NO\n"); 36 } 37 return 0; 38 }
(2)好理解点,中规中矩(218ms)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <set> 6 using namespace std; 7 8 int main() { 9 #ifndef ONLINE_JUDGE 10 freopen("in.txt", "r", stdin); 11 #endif // ONLINE_JUDGE 12 13 int n, m; 14 while (scanf("%d%d", &n, &m) != EOF) { 15 16 int a, r; 17 set<int> mods; 18 set<int> mods_tmp; 19 20 mods.insert(0); 21 for (int i = 0; i < n; i++) { 22 scanf("%d", &a); 23 for (set<int>::iterator it = mods.begin(); it != mods.end(); ++it) { 24 int r = (*it + a) % m; 25 if (r == 0) { 26 printf("YES\n"); 27 return 0; 28 } 29 mods_tmp.insert(r); 30 mods_tmp.insert(a); 31 } 32 mods.insert(mods_tmp.begin(), mods_tmp.end()); 33 mods_tmp.clear(); 34 } 35 printf("NO\n"); 36 } 37 return 0; 38 }
codeforces 577B. Modulo Sum 解题报告
标签:
原文地址:http://www.cnblogs.com/windysai/p/4805829.html