codeforces 577B. Modulo Sum 解题报告

题目链接: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) ),那么就有以下的前缀和向区间和的转化了。

Sr = Sl (mod m)
==> Sr - Sl = 0 (mod m)
==> a[l+1] + a[l+2] .. + a[r] = 0 (mod m)

  而到了 n <= m的情况, 之后就是01背包窝~~写不出来,好惨啊= =

  还是用set浅显易懂。。。。

  轮到我用的方法了(都是参考人的,神奇啦)

  *****************************************

  大体思路:保存选的数的各种组合,求出各种和的不同结果,保存在set容器中的 mods 中。当中要用到另一个set :mods_tmp。用来保存当前处理的数a与mods中的各个和,组合出的但在原mods中没有出现的和。一轮迭代之后,将这个mods_tmp添加到mods中。这样不用下次再算嘛~~~~注意,mod m 最多只会出现 m 种结果:0, 1, 2, ..., m-1。所以不用担心超时。

  顺便说说代码中为什么一开始要插入 0,因为可以只选当前输入的那个 a 嘛~~~哈哈哈·~~~

  (1)这个会比(2)快(124ms)

 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 }

时间: 2024-10-06 07:06:01

codeforces 577B. Modulo Sum 解题报告的相关文章

Codeforces 577B Modulo Sum:数学 结论【选数之和为m的倍数】

题目链接:http://codeforces.com/problemset/problem/448/C 题意: 给你n个数字,给定m. 问你是否能从中选出若干个数字,使得这些数字之和为m的倍数. 题解: 其实就是要找一些数字,使得之和mod m为0. 开一个vector,存当前已经能够构成的数字之和mod m之后的值. 一开始vector为空,然后枚举n个数字a[i],对于每个数字枚举当前vector中的值v[i],将没有出现过的(a[i]+v[i])%m值加入vector中. 最后判断下vec

codeforces 591A. Wizards&#39; Duel 解题报告

题目链接:http://codeforces.com/problemset/problem/591/A 题目意思:其实看下面这幅图就知道题意了,就是Harry 和 He-Who-Must-Not-Be-Named 分别在走廊末端,各发射自己的impulse,其中Harry 的 impulse 速度为 p 米/s,He-...-Named (这个名字太长,姑且写成这样)为 q米/s.然后相遇之后各自回到它们的主人身边,再发射,问第二次相遇的时候,Harry的impulse 离他的位置距离是多少.

CodeForces 250B Restoring IPv6 解题报告

Description An IPv6-address is a 128-bit number. For convenience, this number is recorded in blocks of 16 bits in hexadecimal record, the blocks are separated by colons — 8 blocks in total, each block has four hexadecimal digits. Here is an example o

LeetCode: Combination Sum 解题报告

Combination Sum Combination Sum Total Accepted: 25850 Total Submissions: 96391 My Submissions Question Solution Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The

Codeforces Round #277.5 解题报告

又熬夜刷了cf,今天比正常多一题,比赛还没完但我知道F过不了了,一个半小时贡献给F还是没过--应该也没人Hack,写写解题报告吧= =! 解题报告如下: A题:选择排序直接搞,因为不要求最优交换次数,代码: #include <iostream> #include <algorithm> #include <cstdio> #include <memory.h> #include <vector> #include <stack> #

USACO Section2.3 Zero Sum 解题报告 【icedream61】

zerosum解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 给你N. 把1到N依次写出,每相邻两个数字中间加上一个字符,三选一:'+','-',' '. 如此,便可形成很多表达式,把其中计算结果为0的按字典序输出.[数据范围] 3<=N<

LeetCode: Binary Tree Maximum Path Sum 解题报告

Binary Tree Maximum Path SumGiven a binary tree, find the maximum path sum. The path may start and end at any node in the tree. For example:Given the below binary tree, 1      / \     2   3 SOLUTION 1: 计算树的最长path有2种情况: 1. 通过根的path. (1)如果左子树从左树根到任何一个N

codeforces 495B. Modular Equations 解题报告

题目链接:http://codeforces.com/problemset/problem/495/B 题目意思:给出两个非负整数a,b,求出符合这个等式      的所有x,并输出 x 的数量,如果 x 有无限多个,那么输出 infinity. 想了半个多小时......有个地方想遗漏了. a mod x == b,等价于  a = k*x + b.设 mul = a - b,那么 k*x = mul,然后就不断枚举 mul 的因子,即 kx = mul.由于 mod 出来的结果为 b,那么

codeforces 495A. Digital Counter 解题报告

题目链接:http://codeforces.com/problemset/problem/495/A 这个题目意思好绕好绕~~好绕~~~~~,昨天早上做得 virtual 看不懂,晚上继续看还是,差点就想求救 XX 兽了,最终还是打住,尽量不要依赖人嘛.今天终于想到了,大感动 ~_~ 理解能力有待提高... One of the sticks of the counter was broken    这句话有一点误导人的成分,我刚开始就以为只有一条 stick 坏了= =,再看这句 becau