dp百題進度條[2/100]算法
題目連接dom
題目描述
對於任意一個整數數列,咱們能夠在每兩個整數中間任意放一個符號'+'或'-',這樣就能夠構成一個表達式,也就能夠計算出表達式的值。好比,如今有一個整數數列:17,5,-21,-15,那麼就能夠構造出8個表達式:spa
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
對於一個整數數列來講,咱們能經過如上的方法構造出不一樣的表達式,從而獲得不一樣的數值,若是該數值可以被k整除的話,那麼咱們就稱該數列能被k整除。 在上面的例子中,該數列能被7整除(17+5+(-21)-15=--14),但不能被5整除。如今你的任務是,判斷某個數列是否能被某數整除。code
輸入格式
第一行是一個整數m,表示有m個子任務。接下來就是m個子任務的描述。 每一個子任務有兩行。第一行是兩個整數n和k(1<=n<=10000, 2<=k<=100),n和k中間有一個空格。n 表示數列中整數的個數;k就是須要你判斷的這個數列是否能被k 整除。第二行是數列的n個整數,整數間用空格隔開,每一個數的絕對值都不超過10000。get
輸出格式
輸出文件應有m 行,依次對應輸入文件中的m 個子任務,若數列能被k 整除則輸出 "Divisible",不然輸出 "Not divisible" ,行首行末應沒有空格。string
輸入輸出樣例
輸入 #1
2
4 7
17 5 -21 15
4 5
17 5 -21 15
輸出 #1
Divisible
Not divisibleio
思路一:正常的dp
0/1揹包,本身看就好惹方法
#include<cstdio> #include<cstring> using namespace std; const int MAXN = 10005; int x,k,n; bool dp[MAXN][1005]; inline int mod(int x){ x %= k; if (x < 0) x += k; return x; } int main(){ int t; scanf("%d",&t); while (t--){ scanf("%d %d",&n,&k); memset(dp,false,sizeof(dp)); scanf("%d",&x); dp[0][mod(x)] = true; dp[0][mod(-x)] = true; for (register int i = 1 ; i < n ; i++){ scanf("%d",&x); x = mod(x); for (register int j = 0 ; j < k ; j++){ dp[i][j] = dp[i - 1][mod(j - x)] | dp[i - 1][mod(j + x)]; } } if (t == 0){ if (dp[n - 1][0] == true) printf("Divisible"); else printf("Not divisible"); } else{ if (dp[n - 1][0] == true) printf("Divisible\n"); else printf("Not divisible\n"); } } return 0; }
思路二(我很欽佩的一種作法):
隨機化算法,徹底看臉di
#include<cstdio> #include<cstdlib> using namespace std; int a[10001]; int i,n,T,k,randomm,ans; int main( ) { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(i=1;i<=n;i++) scanf("%d",&a[i]); int tot=500,flag=0; while(tot) { tot--; ans=0; for(i=1;i<=n;i++) { randomm=rand(); if(randomm%2) ans+=a[i]; else ans-=a[i]; } if(ans%k==0) { printf("Divisible\n"); flag=1; break; } } if(!flag) printf("Not divisible\n"); } return 0; }