CF Modulo Sum

来源:互联网 发布:微信micromsg数据恢复 编辑:程序博客网 时间:2024/06/07 06:52
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 a1, a2, ..., an, and a number m.

Check if it is possible to choose a non-empty subsequence aij 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 ≤ 1062 ≤ m ≤ 103) — the size of the original sequence and the number such that sum should be divisible by it.

The second line contains n integers a1, a2, ..., an (0 ≤ ai ≤ 109).

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.

Sample test(s)
input
3 51 2 3
output
YES
input
1 65
output
NO
input
4 63 1 1 3
output
YES
input
6 65 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.

题目的大概意思就是给你两个数字n和m,然后给你n个数字,问从这n个数字中选取任意个数的数字,问能不能使这些数字的和mod m的值为0;

回答yes或no。我是用dp解的,定义num[i]表示对m取余,值为i时,当前数字能够使用的个数,假如num[i]为-1,表示前面任意个数字的和对m取余都不为i。因为初始的时候定义num[0]不为-1,这里当num[m]不为-1时才算达到符合要求的状态。

#include <cstdio>#include <cstring>int n,m,num[1005],s[1005];int main(){    int a,b,w,k;    while ( scanf("%d%d",&n,&m) != EOF )    {        memset(num,-1,sizeof(num));        memset(s,0,sizeof(s));        for(int i = 0; i<n; i ++ )        {            scanf("%d",&a);            if ( a > m || a == 0 )//保存对m取余值相同的数的个数。            {                if ( a % m == 0 ) s[m]++;                else s[a%m]++;            }            else s[a]++;        }        num[0] = 1;//初始化num【0】        b = 0;        for (int i = 1; i <= m; i ++ )        {            if ( !s[i] )continue;//当对m取余为i的值不存在时,跳过。            //printf("%d\n",i);            for (int j = 0; j <= m; j ++ )            {                if ( num[j] != -1 ) num[j] = s[i];//如果前面的任意个数字组合起来对m取余为j,则j可以使用s【i】个i;
            }            for(int j = 0; j <= m; j ++ )            {                if ( b ) break;//b标记是否达到符合要求的状态。                if ( num[j] > 0  )//如果还有i可以使用则进入循环                {                    w = j;                    while ( num[w] > 0 )//如果w还有可以使用的i则继续循环。                    {                      //  printf("%d %d\n",w,w+i);                        if ( w + i < m )                        {                            if ( num[w]-1 <= num[w+i]  )//如果使用i后不能达到更好的状态则结束                                break;                            num[w+i] = num[w]-1 ;//如果能达到更好的状态,则转移该状态。                            w = w+i;                        }                        else                        {                            if ( (w+i) % m == 0 )//如果使用一个i后达到符合要求的状态,则结束。                            {                                b = 1;                                break;                            }                            else                            {                                    if ( num[w]-1 <=  num[(w+i)%m] )//如果使用i后不能达到更好的状态则结束                                     break;                                     num[(w+i)%m] =  num[w]-1;                                     w = (w+i)%m;                            }                        }                    }                }            }            //for(int j = 0; j <= m; j ++ ) printf("%d ",num[j]);            //printf("\n");            if ( b ) break;        }        if ( b ) printf("Yes\n");        else printf("No\n");    }    return 0;}

0 0
原创粉丝点击