1. 程式人生 > 其它 >【CF577B Modulo Sum】題解

【CF577B Modulo Sum】題解

題目連結

題目

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.

給出 \(1\) 個長度為 \(n\) 的序列,以及 \(1\) 個正整數 \(m\)。問這個原序列中是否存在非空子序列,使其元素之和能被 \(m\) 整除。

思路

該不會有人不知道 \(O(nm)\)

的做法吧

先說 \(O(nm)\) 做法,相當於是一個01揹包,每個數選和不選,然而這樣會超時。

於是我們考慮 \(n>m\) 的情況。

此時我們對整個數列做字首和,然後再對 \(m\) 取模。

根據抽屜原理,因為 \(n>m\),所以在 \(n\) 個字首和中必有兩個對 \(m\) 取模於是相等,它們中間那段就是答案。

\(n\leqslant m\) 的情況,\(n\leqslant 10^3\),不會超時。

Code

// Problem: CF577B Modulo Sum
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF577B
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
#define N 100010
int n, m, i, j, k; 
int dp[N], f[N], x; 

signed main()
{
//	freopen("tiaoshi.in", "r", stdin); 
//	freopen("tiaoshi.out", "w", stdout); 
	n=read(); m=read(); 
	if(n>m) return printf("YES"), 0; 
	for(i=1; i<=n; ++i)
	{
		x=read();
		for(j=0; j<m; ++j) f[j]=dp[j];
		for(j=0; j<m; ++j)
			dp[(j+x)%m]+=f[j]; 
		dp[x%m]++; 
	}
	printf("%s", (dp[0] ? "YES" : "NO")); 
	return 0; 
}