题目:给你N个数,在N个数中加入加号或减号,判断能否组成整除K的组合。
分析:dp。状态f(i,j)为前i个数字组成的结果余数可以为j的真值。
状态转移方程:f(i+1,(j±a[i])%k) = max(f(i,j)){ 0 =< j < K }
说明:每次计算前清空数据;计算前把数据先映射到%K的值域。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int a[10004];
int f[10004][104];
int main()
{
int T,N,K;
while ( scanf("%d",&T) != EOF )
while ( T -- ) {
scanf("%d%d",&N,&K);
for ( int i = 0 ; i < N ; ++ i )
scanf("%d",&a[i]);
for ( int i = 0 ; i < N ; ++ i )
a[i] = abs(a[i])%K;
memset( f, 0, sizeof(f) );
f[0][0] = 1;
for ( int i = 0 ; i < N ; ++ i )
for ( int j = 0 ; j < K ; ++ j )
if ( f[i][j] ) {
f[i+1][(j+K+a[i])%K] = 1;
f[i+1][(j+K-a[i])%K] = 1;
}
if ( f[N][0] ) printf("Divisible\n");
else printf("Not divisible\n");
}
return 0;
}