w22116972
3/28/2014 - 4:26 PM

UVA 10036

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;
}