ZOJ 2042 Divisibility (DP)

來源:互聯網
上載者:User

【問題描述】

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.