666RPG 計數dp簡單題

2021-09-12 17:12:39 字數 2015 閱讀 2462

lililalala正在玩一種有 n n個回合的回合制rpg遊戲,初始分數為0,第 i i個回合lililalala有如下兩種選擇。

a.將分數加上 ai ai

b.將分數 ×-1 ×-1

lililalala同樣也很討厭野獸數 666 666,但是他很卻喜歡數字 -666 -666。他想知道有多少種不同的方案使得 n n個回合後分數變為 -666 -666且在任何乙個回合之後分數都不為 666 666。

如果兩種方案有任何乙個回合選擇不同,就認為這兩種方案是不同的。

答案請對 108+7 108+7取模。

輸入包含兩行。

第一行乙個整數 n(1≤n≤300) n(1≤n≤300)。

第二行 n n個整數 a1a2a3...an(-666≤ a1a2a3...an≤666) a1a2a3...an(-666≤ a1a2a3...an≤666)。

輸出一行乙個整數--符合條件的不同方案數。
示例1

3

-333 -333 -333

1
僅一種符合條件的方案

第一回合選擇將分數 ×−1 ×−1。分數為 0 0

第二回合選擇將分數加上 -333 -333。分數為 -333 -333

第三回合選擇將分數加上 -333 -333。分數為 -666 -666

示例2

3

333 333 333

0
示例3

13

518 -643 -503 424 -76 -18 547 26 51 -647 -457 -5 329

2
剛開始拿到這道題的時候,一眼看著是bfs。這是一開始寫的**。

#includeusing namespace std;

int n,ans=0;

int a[305];

void bfs(int x,int sum)

if(sum==666) return;

bfs(x+1,sum+a[x]);

bfs(x+1,-sum);

}int main()

}

看似很完美,但是毫無疑問的超時了。

隊友說是dp,我一下就蒙了,這個題如果要dp不是會爆空間,而且還要處理負數的情況(dp只會簡單dp和數字dp的zhazha)

最後搜了題解發現是簡單的計數dp,其中要還要運用到幾個小技巧。

首先是滾動陣列,這道題的狀態轉移方程是這樣的:

dp[i][j] += dp[i-1][-j] + dp[i-1][j-ai];表示在第i回合下,分數為j的方案數。直接開二維陣列會爆記憶體,所以要用到滾動陣列。可以看出這個狀態方程dp[i][j],只和dp[i-1][-j],dp[i-1][j-ai]有關係。也就是說我現在狀態只和前面一位的狀態有關,再之前的狀態就與我沒有關係了,換種話說就是我是否可以通過一種方法將我不需要的那些資料用新的資料覆蓋掉呢,這樣就可以節省大量的空間。得出:dp[i&1][j] + = dp[!(i&1)][-j] + dp[!(i&1)][j-ai];  

其次是j可以為負數,那我就可以設定乙個足夠大的數,來保證 j加上這個超大數會是乙個正數,那麼我需要的-666分就相當於maxn-666分:dp[i&1][j+maxn/2] + = dp[!(i&1)][-j+maxn/2] + dp[!(i&1)][j-ai+maxn/2];  

接下來貼上**:

#includeusing namespace std;

const int maxn = 666*300*4+5;

const int mod = 1e8+7;

int dp[2][maxn];

int a[301];

int n;

int main()

{ cin>>n;

for(int i=0;i>a[i];

dp[1][0+maxn/2]=1;

for(int i=0;i雖然我思路理解了,不夠對於一計數dp的一些細節還是不太明白,以後要做一點計數dp的題。

666 RPG 計數dp入門

lililalala正在玩一種有 n n個回合的回合制rpg遊戲,初始分數為0,第 i i個回合lililalala有如下兩種選擇。a.將分數加上 ai ai b.將分數 1 1 lililalala同樣也很討厭野獸數 666 666,但是他很卻喜歡數字 666 666。他想知道有多少種不同的方案使...

計數DP,牛客練習賽41B題 666RPG

傳送門 lililalala正在玩一種有 n個回合的回合制rpg遊戲,初始分數為0,第 i i個回合lililalala有如下兩種選擇。a.將分數加上 ai ai b.將分數 1 1lililalala同樣也很討厭野獸數 666 但是他很卻喜歡數字 666 他想知道有多少種不同的方案使得n個回合後分...

牛客練習賽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...