傳送門
lililalala正在玩一種有 n個回合的回合制rpg遊戲,初始分數為0,第 i i個回合lililalala有如下兩種選擇。
a.將分數加上 ai ai
b.將分數 ×-1 ×-1
lililalala同樣也很討厭野獸數 666 ,但是他很卻喜歡數字 -666 -。他想知道有多少種不同的方案使得n個回合後分數變為 -666且在任何乙個回合之後分數都不為 666。
如果兩種方案有任何乙個回合選擇不同,就認為這兩種方案是不同的。
答案請對 10^8+7 取模。
輸入描述:
輸入包含兩行。
第一行乙個整數 n(1≤n≤300) n(1≤n≤300)。
第二行 n n個整數 a1a2a3…an(-666≤ a1a2a3…an≤666) a1a2a3…an(-666≤ a1a2a3…an≤666)。
輸出描述:
輸出一行乙個整數–符合條件的不同方案數。輸入3
-333 -333 -333輸出1
說明僅一種符合條件的方案
第一回合選擇將分數×−1。分數為0
第二回合選擇將分數加上-333。分數為 -333
第三回合選擇將分數加上 -333。分數為 -666輸入3
333 333 333輸出0
輸入13
518 -643 -503 424 -76 -18 547 26 51 -647 -457 -5 329輸出2
計數dp.
dp[i][j]代表第i個回合後分數為j的方案數
則:dp[i][j]=dp[i-1][j-ai]+dp[i-1][-j]
因為開二維記憶體不夠,需要使用滾動陣列, 同時, 避免負數的影響用dp[i][j+add] 來代表第i個回合後分數為j的方案數。因為j最小為300 * -666 這裡取add = 300 * 666。
特判遮蔽所有來自j=666的狀態轉移
計數dp不太熟悉, 卡了很久在 dp[cnt][j+add]=dp[cnt^1] [j-a[i]+add]+dp[cnt^1][-j+add];
之前是分開寫的用了+= 但這裡用到了滾動陣列, 前面一輪算的數會保留到這一輪, 用+= 會造成錯誤。
#include#include#include#includeusing namespace std;
const int add = 300*666, mod = 1e8 + 7;
int a[310];
int dp[2][add * 2]; //j的範圍由300 * -666 到 300 * 666 改為 0 ~ 300 * 666 * 2
int main()}}
printf("%d", dp[n % 2][add - 666]);
}
牛客練習賽41 B 666RPG(計數dp)
思路 我們可以用 則可以得狀態轉移方程為 但是 include using namespace std define ll long long const int n 1e6 7 const int base 301 666 const int mod 1e8 7 int a 305 ll dp 2...
演算法小講堂 動態規劃!之牛客練習賽41 B題
說來實在慚愧,已經很久沒有更新部落格了。反正也沒人看 偷笑 那麼今天就更新一道dp型別的題目。所謂 dp 好,好到頭髮少。另外需要補充的一點是呢,這題我在時限內並沒有寫出來,可謂菜的開花 直接開花 但是我覺得這個dp的手法十分有用,所以我就很厚臉皮更上了一期,當然也會盡量把思路說的的比較詳細啦。看題...
牛客練習賽41
相當於求n個點,已知n條邊,組成各個連通分塊,每個連通分塊有乙個和值,求出最大的幾個和值。用並查集給邊建立聯絡,計算連通塊和是 先找到那個fa點 再給該點加值。include include include include include includeusing namespace std typ...