【問題描述】
Consider an arbitrary sequence ofintegers. One can place + or - operators between integers in the sequence, thusderiving different arithmetical expressions that evaluate to different values.Let us, for example, take the sequence:
17, 5, -21, 15. There are eightpossible expressions:
17 + 5 + -21 + 15 = 16
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 integersdivisible by K if + or - operators can be placed between integers in thesequence in such way that resulting value is divisible by K. In the aboveexample, the sequence is divisible by 7 (17+5+-21-15=-14)
but is not divisibleby 5.
You are to write a program that willdetermine divisibility of sequence of integers.
譯題:
給出N個數,你可以在這N個數中任意地添加+號或-號,求出能不能使算出的結果被K整除。可以則列印“Divisible”,否則列印“Not divisible”
(1 <= N <= 10000, 2 <= K<= 100)
下面是一個例子:
有4個數,分別是17 5 -21 15
17 + 5 + -21 + 15 = 16
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
有8種添法,其中第二種求出的-14能被7整除。
【輸入檔案】
The first line of the input containstwo integers, N and K (1 <= N <= 10000, 2 <= K <= 100) separated bya space.
The second line contains a sequenceof N integers separated by spaces. Each integer is not greater than 10000 byit's absolute value.
注意第一個數是測試資料的組數,多組測試資料一起測。。
【輸出檔案】
Write to the output file the word"Divisible" if given sequence of integers is divisible by K or"Not divisible" if it's not.
The first line of a multiple input isan integer N, then a blank line followed by N input blocks. Each input block isin the format indicated in the problem description. There is a blank linebetween input blocks.
The output format consists of Noutput blocks. There is a blank line between output blocks.
注意:輸出每組結果之間有空格,最後一行無空格,格式不對不能AC,我就是因為格式不對調了一上午。。。。
【輸入範例】
2
4 7
17 5 -21 15
4 5
17 5 -21 15
【輸出範例】
Divisible
Not divisible
【問題分析】
看到題目第一個反映就是枚舉中間添的運算子,算出值在MOD K如果有一個值MOD K=0則輸出“Divisible”。
時間複雜度是O(2N-1)。
但是題目給出的資料量很大,這樣做效率太低了。
因為題目涉及MOD運算,要想簡化問題就需要知道一些基本的MOD運算性質:
A*B mod C=(A mod C*B mod C) mod C
(A+B) mod C=(A mod C+B mod C) mod C
有了這個性質,我們就可以把累加後求餘轉化成求餘後累加(我們把減法看作加負數以後分析只說加法)再求餘。這樣我們的讀入資料就控制在了1-K到K-1的範圍內了。
我們要判斷的就是
所有結果的累加和 MOD K 是否為0。簡記為:
(A+B)mod K=0 or (A+B) mod K<>0
如果我們按數的個數劃分階段,前N-1個數的運算結果 MOD K看做A,第N個數看作B就OK了。
於是我們想到了這樣的狀態:opt[i,j]表示前i個數是否可以得到餘數為J的結果。
那麼狀態轉移方程就是
opt[i,(j-a[i] mod k )modk]=opt[i-1,j] (opt[i-1,j]=true);
opt[i,(j+a[i] mod k) modk]=opt[i-1,j] (opt[i-1,j]=true);
如果opt[n,0]=true就輸出‘Divisible’
#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;int n, k;int a[10001];bool rem[10001][101];int main(){ int t; scanf("%d",&t); while(t--) { int i, j; scanf("%d%d",&n,&k); for(i = 0; i < n; i++) { scanf("%d",&a[i]); a[i] = (a[i] % k + k) % k; //注意有負數 } memset(rem,0,sizeof(rem)); rem[0][a[0]] = true; for(i = 1; i < n; i++) for(j = 0; j < k; j++) if(rem[i-1][j]) rem[i][(j+a[i]+k)%k] = rem[i][(j-a[i]+k)%k] = true; if(rem[n-1][0]) printf("Divisible\n"); else printf("Not divisible\n"); if(t) printf("\n"); //這題的輸出格式要求比較嚴格,注意了。 } return 0;}