UVA 10036
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main(int argc, const char * argv[]) // 用動態規劃的概念,把前面的list可能造成的餘數都存為true
{
int m;
cin >> m;
while (m--) {
int n,k;
cin >> n >> k;
bool remain[k]; // 這裡要注意bool宣告後,要把它初始化false,不然好像有問題
int list[n];
for (int i=0; i<k; i++)
remain[i]=false;
/*
bool remainTmp[k];
for (int j=0; j<k; j++)
remainTmp[j]=false;
*/
set<int> sets; // 因為要放暫存餘數為true的值,但是如果測資很大的話,可能會有很多重複的餘數
set<int>::iterator setIter; // 所以如果用set的話 就可以保證之後在放值進去時 重複的不會被計算 長度保證只有k 速度會加快
for (int i=0; i<n; i++) {
int temp;
cin >> temp;
list[i]=temp;
}
for (int i=0; i<n; i++) {
if (i==0) { // 第一個初始的因為都是false的狀態所以要另外開一個去跑第一個的情形
int rem = list[i]%k >=0 ? list[i]%k : list[i]%k+k;
remain[rem]=true;
}
else {
for (int j=0; j<k; j++) { // 考慮所有餘數的情形
if (i && remain[j]) { // 如果餘數為true 才需要檢查 也就是說有這些餘數在進行下一階段的判斷
remain[j]=false;
int remPlus = (j+list[i])%k >=0 ? (j+list[i])%k : (j+list[i])%k+k;
int remSub = (j-list[i])%k >=0 ? (j-list[i])%k : (j-list[i])%k+k; // 如果餘數為負 需要再加上除數使其變正
// remainTmp[remSub]=true;
// remainTmp[remPlus]=true;
sets.insert(remSub);
sets.insert(remPlus);
}
}
for (setIter=sets.begin(); setIter!=sets.end(); setIter++) // 把有為true的值放進餘數裡 代表這一階段的餘數 ok
remain[*setIter]=true;
sets.clear(); // 千萬記得要把set clear 不然會有問題==
/*
for (int j=0; j<k; j++) {
if (remainTmp[j]) {
remain[j]=true;
remainTmp[j]=false;
}
}
*/
}
}
if (remain[0]) // 如果回圈最後的餘數有為0的是true 所以代表最後有可整除的
cout << "Divisible" <<endl;
else
cout << "Not divisible" <<endl;
}
return 0;
}