题目链接:http://codeforces.com/problemset/problem/448/C
题意:
给你n个数字,给定m。
问你是否能从中选出若干个数字,使得这些数字之和为m的倍数。
题解:
其实就是要找一些数字,使得之和mod m为0。
开一个vector,存当前已经能够构成的数字之和mod m之后的值。
一开始vector为空,然后枚举n个数字a[i],对于每个数字枚举当前vector中的值v[i],将没有出现过的(a[i]+v[i])%m值加入vector中。
最后判断下vector中有没有0就好。
然而直接做是O(nm)的过不了。
这时候就有一个结论:
当n>m时,一定能够找出一些数字,使得它们之和mod m为0。
证明:
令sum[i]为数字a[1 to i]的和mod m后的值。
显然,一定有一对(i,j)使得sum[i]==sum[j] (i<j)。
所以有∑ a[i+1 to j] mod m == 0。得证。
这样当n>m的时候特判一下直接输出,否则再跑上面的做法。
这样复杂度就成O(m^2)的了。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX_M 1005 6 7 using namespace std; 8 9 int n,m; 10 int vis[MAX_M]; 11 vector<int> v; 12 13 int main() 14 { 15 cin>>n>>m; 16 if(n>m) 17 { 18 cout<<"YES"<<endl; 19 return 0; 20 } 21 memset(vis,false,sizeof(vis)); 22 int x; 23 for(int i=1;i<=n;i++) 24 { 25 cin>>x; 26 x%=m; 27 for(int j=0,t=v.size();j<t;j++) 28 { 29 int now=(v[j]+x)%m; 30 if(!vis[now]) 31 { 32 v.push_back(now); 33 vis[now]=true; 34 } 35 } 36 if(!vis[x]) 37 { 38 v.push_back(x); 39 vis[x]=true; 40 } 41 } 42 if(vis[0]) cout<<"YES"<<endl; 43 else cout<<"NO"<<endl; 44 }