1. 程式人生 > >Codeforces 577B Modulo Sum:數學 結論【選數之和為m的倍數】

Codeforces 577B Modulo Sum:數學 結論【選數之和為m的倍數】

fine 題解 直接 pro def ble 個數字 out i++

題目鏈接: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 }

Codeforces 577B Modulo Sum:數學 結論【選數之和為m的倍數】