1710: 整除
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 307 Solved: 59
[Submit][Status][Web Board]
Description
其實,我們知道,如果給你一串序列,例如:17 5 -21 15,我們可以在之間添加上符號(只能是+,或者 - )。使其得出不同的結果:
17 + 5 + -21 - 15 = -14
17 + 5 - -21 + 15 = 58
17 + 5 - -21 - 15 = 28
17 - 5 + -21 + 15 = 6
17 - 5 + -21 - 15 = -24
17 - 5 - -21 + 15 = 48
17 - 5 - -21 - 15 = 18
現在呢,再給你一個數m(m<=100),就是問你給出的序列s,s的所有組合中是不是存在一種能整除m的,存在的話輸出Yes,沒有的話輸出No
Input
第一行n,m
第二行 n(n<=10000)個數字
Output
輸出Yes or No
Sample Input
4 7
17 5 -21 15
Sample Output
Yes
解析:dp[i]j]: i表示前i個數,j表示前i個數“+,-”後的值
dp[i][j]=1表示前i個數進行“+,-”所可以得到的j值。dp[i][j]=0表示不存在。
這裏怎麼枚舉所有的“+,-”呢?代碼中說明。
#include<bits/stdc++.h>
using namespace std;
#define e exp(1)
#define pi acos(-1)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int n,m,a[10005],dp[10005][105];
int main()
{
while(~scanf("%d%d",&n,&m))
{
mem(dp,0);
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
a[i]=(a[i]%m+m)%m;
}
dp[0][a[0]]=1;
for(int i=1; i<n; i++)
{
for(int j=0; j<=m; j++)
{
if(dp[i-1][j])//表示前面i-1可以的到j的值
{
dp[i][((j+a[i])%m+m)%m]=1;//進行枚舉j“+,-”a[i]後形成新的值
dp[i][((j-a[i])%m+m)%m]=1;
}
}
}
if(dp[n-1][0])puts("Yes");
else puts("No");
}
return 0;
}