您的位置:首页 > 其它

CF Modulo Sum

2015-09-13 19:04 239 查看
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 ≤ 106, 2 ≤ 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 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.

题目的大概意思就是给你两个数字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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: