Codeforces 577B. Modulo Sum (数学 + DP)

23 篇文章 0 订阅

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(nm) 显然不行
发现当 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(mm)

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值