codeforces #319 B - Modulo Sum (抽屉原理,dp)

B - Modulo Sum

Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u

Submit Status

Description

You are given a sequence of numbers a1, a2, ..., an, and a number m.

Check if it is possible to choose a non-empty subsequence aij such that the sum of numbers in this subsequence is divisible by m.

Input

The first line contains two numbers, n and m (1 ≤ n ≤ 106, 2 ≤ m ≤ 103) — the size of the original sequence and the number such that sum should be divisible by it.

The second line contains n integers a1, a2, ..., an (0 ≤ ai ≤ 109).

Output

In the single line print either "YES" (without the quotes) if there exists the sought subsequence, or "NO" (without the quotes), if such subsequence doesn‘t exist.

Sample Input

Input

3 51 2 3

Output

YES

Input

1 65

Output

NO

Input

4 63 1 1 3

Output

YES

Input

6 65 5 5 5 5 5

Output

YES

Hint

In the first sample test you can choose numbers 2 and 3, the sum of which is divisible by 5.

In the second sample test the single non-empty subsequence of numbers is a single number 5. Number 5 is not divisible by 6, that is, the sought subsequence doesn‘t exist.

In the third sample test you need to choose two numbers 3 on the ends.

In the fourth sample test you can take the whole subsequence.

背包还是理解的不够透彻..

因为每次都是用那个一维形式的.

这道题的做法类似01背包.

此外还可以有一个优化...

当n>m的时候...根绝抽屉原理..一定为yes..

复杂度可以从o(nm)优到 o(m^2)

 1 /*************************************************************************
 2     > File Name: code/#319/BB.cpp
 3     > Author: 111qqz
 4     > Email: [email protected]
 5     > Created Time: 2015年09月15日 星期二 21时31分12秒
 6  ************************************************************************/
 7
 8 #include<iostream>
 9 #include<iomanip>
10 #include<cstdio>
11 #include<algorithm>
12 #include<cmath>
13 #include<cstring>
14 #include<string>
15 #include<map>
16 #include<set>
17 #include<queue>
18 #include<vector>
19 #include<stack>
20 #include<cctype>
21 #define y1 hust111qqz
22 #define yn hez111qqz
23 #define j1 cute111qqz
24 #define ms(a,x) memset(a,x,sizeof(a))
25 #define lr dying111qqz
26 using namespace std;
27 #define For(i, n) for (int i=0;i<int(n);++i)
28 typedef long long LL;
29 typedef double DB;
30 const int inf = 0x3f3f3f3f;
31 const int N=1E3+7;
32 int n,m;
33 int a[N];
34 int dp[N][5];
35 int main()
36 {
37   #ifndef  ONLINE_JUDGE
38
39   #endif
40     cin>>n>>m;
41     if (n>m)
42     {
43     puts("YES");
44     return 0;
45     }
46     for (int i = 1 ; i <= n ; i++)
47     {
48     int x;
49     scanf("%d",&x);
50     a[i] = x % m;
51     }
52     int x = 0 ;
53     for ( int i = 1 ; i <= n ; i++)
54     {
55
56     dp[a[i]][1-x] = 1;
57     for ( int j = 1 ; j < m ; j++)
58     {
59         if(dp[j][x])
60         {
61
62         dp[(j+a[i])%m][1-x] = 1;
63         dp[j][1-x] = 1;
64         }
65     }
66     x = 1-x;
67     if (dp[0][x])
68     {
69         puts("YES");
70         return 0;
71     }
72
73     }
74     puts("NO");
75     return 0;
76
77
78
79
80
81  #ifndef ONLINE_JUDGE
82   fclose(stdin);
83   #endif
84     return 0;
85 }

时间: 2024-10-29 08:22:48

codeforces #319 B - Modulo Sum (抽屉原理,dp)的相关文章

CodeForces 23C Oranges and Apples 抽屉原理

题目链接:点击打开链接 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf 10000000 #define l

【CodeForces 577B】Modulo Sum

题 题意 给你n(1 ≤ n ≤ 106)个数a1..an(0 ≤ ai ≤ 109),再给你m( 2 ≤ m ≤ 103)如果n个数的子集的和可以整除m,则输出YES,否则NO. 分析 分两种情况: 当n>m时,s[i]表示前i张钱共多少钱,s[i]%m的取值为0到m-1,由抽屉原理可知,s[i]一定有重复的,假如重复的是s[l]和s[r],那么s[r]-s[l]也就是l+1到r这些钱加起来就是m 的倍数.故答案为YES. 当n≤m时,我们用dp[i][j]==1表示前i张钱可以得到对m取余为

CodeForces - 1073E :Segment Sum (数位DP)

You are given two integers l l and r r (l≤r l≤r ). Your task is to calculate the sum of numbers from l l to r r (including l l and r r ) such that each number contains at most k k different digits, and print this sum modulo 998244353 998244353 . For

CF 577B Modulo Sum

题意:给一个长度为n的正整数序列,问能不能找到一个不连续的子序列的和可以被m整除. 解法:抽屉原理+dp.首先当m<n时一定是有答案的,因为根据抽屉原理,当得到这个序列的n个前缀和%m时,一定会出现两个相同的数,这两个前缀和相减得到的序列和一定可以被m整除.当n<=m时,dp一下就可以了,类似01背包. 其实可以直接dp,只要滚动数组+在找到答案时break就可以了,同样因为抽屉原理,当枚举到第m+1个物品的时候就一定会得到解,所以最后复杂度O(m^2). 代码: #include<st

cf 319 div 2 Modulo Sum 数论+DP

 Modulo Sum 题目抽象:给你你一个整数数组,能否从中取出一些树,使得他们的和能被m整除. 分析:见代码注释. 1 #include <cstdio> 2 #include <cstring> 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, &

Codeforces 75D Big Maximum Sum 最大子段和 dp

题目链接:点击打开链接 题意: 第一行 n m n个vector 下面n行 第一个数字u表示vector 的大小,然后后面u个数字给出这个vector 最后一行m个数字 表示把上面的vector拼接起来 得到一个大序列,求这个大序列的最大子段和 先预处理出每个vector的最大子段和,左起连续最大,右起连续最大,所有数的和 然后dp 一下.. #include <cstdio> #include <iostream> #include <algorithm> #incl

51NOD 1103 N的倍数(抽屉原理)

传送门 一个长度为N的数组A,从A中选出若干个数,使得这些数的和是N的倍数. 例如:N = 8,数组A包括:2 5 6 3 18 7 11 19,可以选2 6,因为2 + 6 = 8,是8的倍数. Input 第1行:1个数N,N为数组的长度,同时也是要求的倍数.(2 <= N <= 50000) 第2 - N + 1行:数组A的元素.(0 < A[i] <= 10^9) Output 如果没有符合条件的组合,输出No Solution. 第1行:1个数S表示你所选择的数的数量.

Codeforces Div.301D Bad Luck Island(概率dp+记忆化搜索)

一道概率dp问题. 题目链接:http://codeforces.com/contest/540/problem/D 题目大意:一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j][k]来存储i个石头,j个剪刀,k个布时,某物种的存活概率,共dp三次,算出三个物种分别的概率. 首先,我们需要把对应想求的物种概率初始化,这里以石头为例,那么对于i从1到r,不难理解dp[i][0][0]=

POJ 3370 Halloween treats(抽屉原理)

Halloween treats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6631   Accepted: 2448   Special Judge Description Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets