codeforces 577B Modulo Sum

题目链接 http://codeforces.com/contest/577/problem/B

题意:给定一个数组a,长度为n,请问从数组中是否有个子序列的和总和能被m整出。

n<=1,000,000   m<=1000,a[i]<=1,000,000,000。

题目思路:

把a[i]整除m,可以把a[i]的数据范围放置在[0,m)之间。

然后开一个数组dp,dp[i]表示若干的数相加的余数可以达到i的。

那么再每个数都去扫一遍dp,每次更新dp可达到的i。

时间复杂度O(n*m)。

更新时要延迟更新,不能直接更新,不然的话,新的输入会被继续计算。

然后,发现当n>m时,答案一定是YES,速度可以被优化。

这是利用余数的性质发现的。

代码如下:

#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long LL;
typedef long long ll; 
const int maxn = 1e6+6;
const int modn = 1e9+7;
const int INF = 0x3f3f3f3f;
char str[maxn];
int a[maxn];
int s[maxn];
int temp[maxn];
void show(int a[],int n){
	for(int i=0;i<n;i++){
		printf("%d ",a[i]);
	}printf("\n");
}
int main(){
//	freopen("C:\\Users\\lenovo\\Desktop\\data.in","r",stdin);
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF){
		memset(s,0,sizeof(s));
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
		}
		if(n>=m){
			printf("YES\n");
			
		}else{
			for(int i=0;i<n;i++){
				a[i]%=m;
				int idx = 0;
			
		//		printf("a[%d]=%d\n",i,a[i]);
				for(int j=0;j<m;j++){
		//			printf("s[%d]=%d\n",j,s[j]);
					if(s[j]==1){
					//	printf("%d\n",(j+a[i])%m);
						
						temp[idx++] = (j+a[i])%m;
					}

				}
		
				for(int j=0;j<idx;j++){
					s[temp[j]] = 1;
				}
				s[a[i]] = 1;
				

			}
	//		show(s,m);
			if(s[0]==1){
				puts("YES");
			}else{
				puts("NO");
			}
			
			
		}
		
		
	}
}

猜你喜欢

转载自blog.csdn.net/qq_25955145/article/details/81301274
今日推荐