挑戰P66 有關計數問題的dp

2021-07-10 13:00:02 字數 1544 閱讀 3847

1.劃分數

有n個相同的物品,將他們劃分為不超過m組的劃分方法,求出劃分方法模m的餘數

input:4 3

ouput:4

這是關於整數劃分的題目,設

dp[i][j]為將i劃分為不超過j組的劃分方法,則,

若任意劃分中的ai>0,則對應dp[i-j][j]的劃分方法

若存在ai==0,則對應dp[i][j-1]

所以,dp[i][j]=dp[i-j][j]+dp[i][j-1]

注意邊界處理,dp[0][0]=1,0<=i<=n,1<=j<=m,

#include#include#include #include using namespace std;

const int maxn=10010;

int n,m,dp[maxn][maxn];

int solve(int n,int m)

}/*for(int i=0;i<=n;i++)

即從i個物品中取出j個,可以從i-1個物品中選出j-k個,再從第i種物品中取出k個

,但是這種定義複雜度比較大。我們可以看出,其實在向右求解的時候會有重複求解,所以,轉移方程還可以化成:

sum=sum+dp[i-1][j]-dp[i-1][j-1-a[i]];

剛開始這化解不太懂,反應能力理解能力太差了,後來模擬一遍才慢慢理解,。。

所以,遞推方程為:

dp[i][j]=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1-a[i]];

這道題有個很重要的思想就是先寫出比較簡單的轉移方程,然後慢慢找出子結構重複的部分再化簡。

#include#include#include #include using namespace std;

const int maxn=10010;

int n,m,dp[maxn][maxn],a[maxn];

int solve(int n,int m)

}/*for(int i=0;i<=n;i++)

{for(int j=0;j<=m;j++)

cout<>n>>m;

for(int i=1;i<=n;i++)

cin>>a[i];

cout<

P1980 計數問題

題目描述 試計算在區間 1 到 n 的所有整數中,數字 x 0 x 9 共出現了多少次?例如,在 1 到 11 中,即在 1 2 3 4 5 6 7 8 9 10 11 中,數字 1 出現了 4 次。輸入輸出格式 輸入格式 輸入檔名為 count.in。輸入共 1 行,包含 2 個整數 n x,之間...

P1980 計數問題

試計算在區間 11 到 nn的所有整數中,數字x 0 x 9 x 0 x 9 共出現了多少次?例如,在 11到1111中,即在 1,2,3,4,5,6,7,8,9,10,111,2,3,4,5,6,7,8,9,10,11 中,數字 11 出現了 44 次。輸入格式 22個整數n,xn,x,之間用乙個...

洛谷 P1980 計數問題

題目描述 試計算在區間 1 到 n 的所有整數中,數字x 0 x 9 共出現了多少次?例如,在 1到 11 中,即在 1,2,3,4,5,6,7,8,9,10,11 中,數字 1 出現了 4 次。輸入格式 2個整數n,x之間用乙個空格隔開。輸出格式 1個整數,表示x出現的次數。輸入輸出樣例 輸入樣例...