Description
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
We call the sequence of integers divisible by K if + or - operators can be placed between integers in the sequence in such way that resulting value is divisible by K. In the above example, the sequence is divisible by 7 (17+5+-21-15=-14) but is not divisible by 5.
You are to write a program that will determine divisibility of sequence of integers.
Input
The second line contains a sequence of N integers separated by spaces. Each integer is not greater than 10000 by it's absolute value.
Output
Sample Input
4 7 17 5 -21 15
Sample Output
Divisible
用到一个公式
(a + b) % c = (a % c + b % c) % c
当a小于0时 a对c的余数 是 a % c + c
一个简单的DP,不用把数字存起来,直接算就好。
AC代码 :
使用了位运算来简化空间复杂度,也可以使用滚动数组。(位运算的原理类似于滚动数组,把int的前两位当作第一层数据和第二层然后每次结束右移单位1,覆盖数据)
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define fn(i,n) for(int i = 0; i < n; i++)
int dp[110];
int main(){
int n, k, t;
while(scanf("%d %d",& n,& k) != EOF){
memset(dp,0,sizeof(dp));
cin >> t;
t = (t % k + k) %k; //无论t的正负取其余数
dp[t] = 1;
fn(i,n - 1){
cin >> t;
t %= k;
if(t == 0) continue; //其实t = 0的话也可以接着算,不过为了省时间还是判断一下
fn(j,k) if(dp[j] & 1){ //判断上一个数时是否有余数
dp[(j + t + k) % k] |= 2; //第二位,置1
dp[(j - t + k) % k] |= 2;
}
fn(j,k) dp[j] >>= 1; //覆盖上一组数据
}
if(dp[0])cout << "Divisible" << endl;
else cout << "Not divisible" << endl;
}
return 0;
}