Description
You are given a sequence of numbers a 1, a 2, …, a n, and a number m.
Check if it is possible to choose a non-empty subsequence a i j 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 a 1, a 2, …, a n (0 ≤ a i ≤ 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.
Examples
Input
3 5
1 2 3
Output
YES
Input
1 6
5
Output
NO
Input
4 6
3 1 1 3
Output
YES
Input
6 6
5 5 5 5 5 5
Output
YES
Solution
有n个数,问是否能选出若干数,其和为m的倍数
首先肯定考虑直接背包,但时间复杂度
O
(
n
∗
m
)
O(n*m)
O(n∗m) 显然不行
发现当
n
>
m
n > m
n>m 时答案肯定为YES,粗略证明如下:
假设当 n > m 不存在若干数的和为m的倍数
则前 [1, m] 个数的前缀和%m 一定互不相同 (否则就可以选出一段连续的数和
%
m
=
=
0
\%m == 0
%m==0)
即一共有
m
m
m 种不同的前缀和 占满了 0 ~ (m-1)
故第
m
+
1
m + 1
m+1 个数的前缀和一定会与之前的相同,所以必能选出一段和
%
m
=
=
0
\%m == 0
%m==0
所以背包复杂度实际为 O ( m ∗ m ) O(m*m) O(m∗m)
Code
int a[maxn];
bool dp[maxn][2];
int main() {
int n,m;scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i){
scanf("%d",&a[i]); a[i]%=m;
}
if(n > m) {printf("YES\n");return 0;}
int op = 0;
for(int i = 1;i <= n;++i){
op ^= 1;
for(int j = 0;j < m;++j) dp[j][op] = dp[j][op^1];
dp[a[i]][op] = true;
for(int j = 0;j < m;++j){
if(dp[j][op^1]) dp[(j+a[i])%m][op] = true;
}
}
if(dp[0][op]) printf("YES\n"); else printf("NO\n");
return 0;
}