poj1745 - Divisibility
NとKを与えて、次に、正負にかかわらず、N個の整数を与え、このN個の数のうち、2個の数の間に(すなわちN-1の位置)プラス記号またはマイナス記号を追加し、演算した値をKに対して余剰を取り、余剰が0に等しい場合はDivisibleを出力し、そうでなければNot divisibleを出力して問題を解く構想:4 7 17 5-21 15を例にまず1つの数を取り、言うまでもなく、最初の数の前に記号を付けないのが本体であり、それ自体が直接Kに余剰を取ると、17を取るときに余剰が2になる個5,(2+5)対7取余が0(2-5)対7取余が4(取余の負数を正)では、前の2つの数に余剰が0と4もう一つの-21(0+21)対7取余が0(0-21)対7取余が0(0-21)対7取余が0(4+21)対7取余が4(4-21)対7取余が4もう一つ-15と同様(0+15)%7=1(0-15)%7=6(4+15)%7=5(4-15)%7=3同理は法則を見つけることができ、dp[i][j]を前のi個の数の剰余を定義するのはjが成立するかどうか、1が成立するかどうか、0が成立しないならば、dp[N][0]が1であれば、1つの数を構成してKに剰余を0にすることができ、dpを0に初期化することができる
そしてdp[1][a[1]%k]=1 for i=2 to N do for j=0 to K do if(dp[i-1][j])dp[i][j+a[i]%k]=1; dp[i][(j - a[i])%k] = 1; if end for end for end
そしてdp[1][a[1]%k]=1 for i=2 to N do for j=0 to K do if(dp[i-1][j])dp[i][j+a[i]%k]=1; dp[i][(j - a[i])%k] = 1; if end for end for end
#include
using namespace std;
#define MAXN 10001
int dp[MAXN][101];
int posmod(int n,int k){
n = n % k;
while(n < 0) n+=k;
return n;
}
int main(){
int n,k;
int i ,j ,tmp;
int a[MAXN];
while(cin>>n>>k){
memset(dp,0,sizeof(dp));
for(i = 1;i <= n;i++) cin>>a[i];
dp[1][posmod(a[1],k)] = 1;
for(i = 2;i <= n;i++){
for(j = 0;j < k;j++){
if(dp[i - 1][j]){
dp[i][posmod(j + a[i],k)] = 1;
dp[i][posmod(j - a[i],k)] = 1;
}
}
}
if(dp[n][0]){
cout<