题目:A. Sticker Album
题意大意:买卡包,每包里有卡片[A,B]张,获得每个卡片的概率都相同,问买多少卡包能组成N张卡片的期望。
设dp[i]为能组成n-i张卡片的期望卡包的数量。
可以得到转移方程
d
p
[
i
]
=
d
p
[
i
+
A
]
+
1
+
.
.
.
+
d
p
[
i
+
B
]
+
1
B
−
A
+
1
dp[i]=\frac{dp[i+A]+1+...+dp[i+B]+1}{B-A+1}
dp[i]=B−A+1dp[i+A]+1+...+dp[i+B]+1
由于范围过大,线性递推,sum维护dp[i+A]-dp[i+B]的总和可以得出答案。
A可以为0,此时方程右边也出现了的dp[i],特判移向在进行转移,之后可理解为1-B的转移。
dp[N]以及大于N的是0。
#include<bits/stdc++.h>
#define mmp make_pair
#define inf 0x3f3f3f3f
#define llinf 0x7fffffffffffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
typedef double ld;
const ll mod=1e9+7;
const int maxn=3e6+10;
double dp[maxn];
int main() {
int N,A,B;
scanf("%d %d %d",&N,&A,&B);
double sum=0.0;
for(int i=N+A;i<=N+B;++i) {
dp[i]=0.0;
}
double fm=(B-A+1)*1.0;
dp[N]=0.0;
if(A) {
for(int i=N-1;i>=0;--i) {
dp[i]=(sum)/fm+1.0;
sum-=dp[i+B];
sum+=dp[i+A-1];
}
}
else {
for(int i=N-1;i>=0;--i) {
dp[i]=(sum+fm)/(fm-1.0);
sum-=dp[i+B];
sum+=dp[i];
}
}
printf("%.8lf",dp[0]);
return 0;
}