題目連結: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 }