题目传送门
题意: 你要凑齐n张卡片,市面上有一些卡片包,每一包中有一些卡片,每一包中卡片的数量独立,为[a,b]区间中的随机整数值,问你期望买多少包,才能凑齐n张卡片。
思路: 考虑用f[i]表示当手里有i张卡片的时候,还期望需要购买多少包。那么出状态f[n]=0,我们要求f[0]。明确目标之后考虑状态转移,我们买一包,至少得到a张卡片,至多得到b张卡片。那么f[i]就要从f[i+a]~f[i+b]转移过来,即 f [ i ] = ∑ ( f [ j ] + 1 ) b − a + 1 , j ∈ [ i + a , i + b ] f[i]=\sum \frac{(f[j]+1)}{b-a+1},j∈[i+a,i+b] f[i]=∑b−a+1(f[j]+1),j∈[i+a,i+b]。但是如果a等于0,需要特殊处理。根据这个式子,把f[i]提到一边,转化得到 f [ i ] = ∑ f [ j ] + 1 b − a + 1 + 1 b − a , j ∈ [ a + 1 , b ] f[i]=\sum \frac{f[j]+1}{b-a}+1+\frac{1}{b-a},j∈[a+1,b] f[i]=∑b−af[j]+1+1+b−a1,j∈[a+1,b]。
代码:
#include<bits/stdc++.h>
#define endl '\n'
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
int x=0,f=1;
char ch=gc();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=gc();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=gc();
}
return x*f;
}
using namespace std;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-7;
double f[N],suf[N];
int solve()
{
int n,a,b;
cin>>n>>a>>b;
f[n] = 0;
suf[n] = 0;
for(int i=n-1; i>=0; i--)
{
if(a!=0)
f[i] = (suf[i+a]-suf[i+b+1])/(b-a+1)+1;
else
f[i] = (suf[i+a+1]-suf[i+b+1]+(b-a+1))/(b-a);
suf[i] = suf[i+1]+f[i];
}
printf("%.7f",f[0]);
}
signed main()
{
// int _;
// cin>>_;
// while(_--)
solve();
return 0;
}