MZOJ
概率dp
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示一个点被刷了
i
i
i次最后为
j
j
j的颜色的概率
转移方程式
f
[
i
+
1
]
[
j
]
+
=
f
[
i
]
[
j
]
∗
0.5
    
f[i+1][j]+=f[i][j]*0.5\;\;
f[i+1][j]+=f[i][j]∗0.5应为
i
i
i在第
i
+
1
i+1
i+1之后有
1
2
\frac{1}{2}
21的概率会变,等于说是选还是不选
f [ i + 1 ] [ ( j ∗ x )    m o d    c ] + = f [ i ] [ j ] / ( 2 ∗ c )        f[i+1][(j*x)\;mod\;c]+=f[i][j]/(2*c)\;\;\; f[i+1][(j∗x)modc]+=f[i][j]/(2∗c) (x枚举颜色) ~~ 乘以 1 2 \frac{1}{2} 21是因为可能不选这个方块
Code
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(register int (i)=(a);(i)<=(b);(i)++)
#define don(i,a,b) for(register int (i)=(a);(i)>=(b);(i)--)
using namespace std;
const int maxn=1e6+10;
const int maxm=1e3+10;
int T,n,c,k,cnt[maxn],tot;
double f[maxm][maxm],ans;
template <class t> inline void read(t &x) {
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
void init() {
memset(f,false,sizeof(f));
memset(cnt,false,sizeof(cnt));
tot=0,ans=0;
read(n),read(c),read(k);
rep(i,1,k) {
int l,r;
read(l),read(r);
rep(j,l,r) {
cnt[j]++;
tot=max(tot,cnt[j]);
}
}
}
void work() {
read(T);
while(T--) {
init();
f[0][1]=1;
rep(i,0,tot-1) {
rep(j,0,c-1) {
f[i+1][j]+=f[i][j]/2;
rep(x,0,c-1) f[i+1][(j*x)%c]+=f[i][j]/(2*c);
}
}
rep(i,1,n)
rep(j,0,c-1)
ans+=f[cnt[i]][j]*j;
printf("%.9f\n",ans);
}
}
int main() {
freopen("input.txt","r",stdin);
//readdata();
work();
return 0;
}