题意:给三个骰子,分别有k1,k2,k3个面,每个面朝上的概率相同。自己玩游戏,有一个计时器,计数器开始时为0,每次扔骰子,如果第一个为a,第二个为b,第三个为c就把计数器清零,否则计时器加上当前三个骰子的和,问当计数器大于n是的期望是多少
自己想的时候,求来求去都会发现是有环的,就是求a需要b,求b需要a,然后就不会了。。然后就百度了题解= =,这个题中也就是求dp[k]需要用dp[0],然后导dp[0]需要dp[k]。然后这道题用另外的一个式子表示了dp[k],使dp[0]只和这个式子中的系数有关,系数又能通过递推求出来,于是就能做了= =
代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int mod = 1e9+7;
#define ll long long
const int maxn = 610;
double a[maxn];
double b[maxn];
double p[100];
int main(){
int T;
cin>>T;
while(T --){
int n,ka,kb,kc,A,B,C;
cin>>n>>ka>>kb>>kc>>A>>B>>C;
for(int i = 0;i < maxn;i ++){
a[i] = b[i] = 0.0;
}
double pp = 1.0/(ka*kb*kc);
for(int i = 3;i < 100;i ++)p[i] = 0.0;
for(int i = 1;i <= ka;i ++){
for(int j = 1;j <= kb;j ++){
for(int k = 1;k <= kc;k ++){
if(i == A&&j == B&&k == C)continue;
p[i+j+k] += pp;
}
}
}
for(int i = n;i >= 0;i --){
for(int j = 3;j <= ka+kb+kc;j ++){
a[i] += a[i+j]*p[j];
b[i] += b[i+j]*p[j];
}
a[i] += pp;
b[i] += 1.0;
//cout<<a[i]<<' '<<b[i]<<endl;
}
printf("%.8lf\n",b[0]/(1-a[0]));
}
return 0;
}