Modulo Sum(背包 + STL)

  • Post author:
  • Post category:其他



Modulo Sum
time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a sequence of numbers



a


1

,

a


2

, …,

a



n


, and a number



m

.



Check if it is possible to choose a non-empty subsequence



a



i



j




such that the sum of numbers in this subsequence is divisible by


m

.



Input

The first line contains two numbers,



n


and



m


(

1 ≤

n

≤ 10

6

,


2 ≤

m

≤ 10

3

) — the size of the original sequence and the number such that sum should be divisible by it.








The second line contains



n


integers



a


1

,

a


2

, …,

a



n



(

0 ≤

a



i


≤ 10

9

).






Output

In the single line print either ”

YES” (without the quotes) if there exists the sought subsequence, or ”

NO” (without the quotes), if such subsequence doesn’t exist.

Examples
input
3 5 1 2 3

output
YES

input
1 6 5

output
NO

input
4 6 3 1 1 3

output
YES

input
6 6 5 5 5 5 5 5

output
YES

Note

In the first sample test you can choose numbers


2

and


3, the sum of which is divisible by


5.






In the second sample test the single non-empty subsequence of numbers is a single number


5. Number


5

is not divisible by


6, that is, the sought subsequence doesn’t exist.






In the third sample test you need to choose two numbers


3

on the ends.


In the fourth sample test you can take the whole subsequence.

题意:

取任意个数的和能否组成M的倍数;宇神用背包写的,参谋了下,很聪明的解法,还可以用set做;

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1e3 + 100;
int num[MAXN * MAXN];
int v[MAXN * MAXN];
int dp[25 * MAXN][MAXN];
int val[MAXN * MAXN];
int main(){
    int n, m;
    while(~scanf("%d%d", &n, &m)){
        memset(num, 0, sizeof(num));
        memset(v, 0, sizeof(v));
        memset(dp, 0, sizeof(dp));
        memset(val, 0, sizeof(val));
        int tp = 0;
        int temp;
        int ans = 0;
        for(int i = 0; i < n; i++){
            scanf("%d", &temp);
            if(temp == m){
                ans = 1;
            }
            if(!num[temp % m])
                v[tp++] = temp % m;
            num[temp % m]++;
        }
        n = tp;
        /*
        printf("tp = %d\n",tp);
        for(int i = 0; i < tp; i++){
            printf("v = %d num = %d \n", v[i], num[v[i] ]);
        }puts("");
        */
        tp = 0;
        for(int i = 0; i < n; i++){
            for(int j = 1; j <= num[v[i]]; j <<= 1){
                if(j * v[i] % m == 0){
                    ans = 1;
                }
                num[v[i]] -= j;
                val[tp++] = j * v[i] % m;
            }
            if(num[v[i]] > 0){
                if(v[i] * num[v[i]] % m == 0)
                    ans = 1;
                val[tp++] = v[i] * num[v[i]] % m;
            }
        }
        /*
        printf("tp = %d\n",tp);
        for(int i = 0; i < tp; i++){
            printf("v = %d num = %d \n", val[i], num[v[i] ]);
        }puts("");
        */
        dp[0][v[0]] = 1;dp[0][0] = 1;
    //    printf("ans = %d\n",ans);
        for(int i = 0; i < tp - 1; i++){
            for(int j = 0; j <= m; j++){
                if(dp[i][j]){
                //    printf("i = %d j = %d\n",i,j);
                    dp[i + 1][j] = 1;
                    if((j + val[i + 1]) % m == 0){
                        ans = 1;
                    }
                    dp[i + 1][(j + val[i + 1]) % m] = 1;
                }
            }
        }
        if(ans)puts("YES");
        else puts("NO");
    }
    return 0;
}

set:

#include<iostream>
#include<cmath>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
const int MAXN = 1e6 + 100;
int main(){
    int n, m;
    while(~scanf("%d%d", &n, &m)){
        int temp, ans = 0;
        set<int>st, _st;
        st.insert(0);
        set<int>::iterator iter;
        for(int i = 0; i < n; i++){
            scanf("%d", &temp);
            for(iter = st.begin(); iter != st.end(); iter++){
                if((*iter + temp) % m == 0){
                    printf("YES\n");
                    return 0;
                }
                _st.insert((*iter + temp) % m);
            }
            st.insert(_st.begin(), _st.end());
            _st.clear();
        }
        puts("NO");
    }  
    return 0;
}

vector:

#include<iostream>
#include<cmath>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
const int MAXN = 1e6 + 100;
int vis[MAXN];
int main(){
	int n, m;
	while(~scanf("%d%d", &n, &m)){
		int temp, ans = 0;
		vector<int>st, _st;
		st.push_back(0);
		memset(vis, 0, sizeof(vis));
		for(int i = 0; i < n; i++){
			scanf("%d", &temp);
			if(ans)continue;
			for(int i = 0; i < st.size(); i++){
				int x = (st[i] + temp) % m;
				if(x == 0){
					ans = 1;
					break;
				}
				if(!vis[x])vis[x] = 1,_st.push_back(x);
			}
			for(int i = 0; i < _st.size(); i++){
				st.push_back(_st[i]);
			}
			_st.clear();
		}
		if(ans)puts("YES");
		else puts("NO");
	}  
	return 0;
}