NOI模拟(3.6)Assignment
Solution
看看应该是一道dp
可以有这样一个思路
令f(i,j)为构造出的序列长度为i,当前填入序列第j种数,为了限制众数的出现次数,要去除所有众数出现次数大于限定的情况
因此,f(k,i,j)=f(k,i-1,j-1)+f(k,i-1,j)-f(k,i-k-1,j-1),其中k代表限定众数出现次数为k
最后乘上一个组合数就是答案了
#include <stdio.h> #include <string.h> template<class T> inline void read(T &x) { int c=getchar(); for(x=0;c<48||c>57;c=getchar()); for(;c>47&&c<58;c=getchar())x=(x<<1)+(x<<3)+c-48; } int T,m,n; long double C[255],f[255][255][255],g[255],ans; int main() { freopen("assignment.in","r",stdin); freopen("assignment.out","w",stdout); for(int k=1;k<=250;k++) { f[k][0][0]=1; for(int i=1;i<=250;i++) for(int j=1;j<=i;j++) { f[k][i][j]=f[k][i-1][j-1]+f[k][i-1][j]; if(i-k-1>=0)f[k][i][j]-=f[k][i-k-1][j-1]; } } for(read(T);T;T--) { read(m),read(n); C[0]=1; for(int i=1;i<=m;i++) C[i]=C[i-1]*(n-i+1)/i; for(int k=1;k<=m;k++) { g[k]=0; for(int j=1;j<=m;j++) g[k]+=f[k][m][j]*C[j]; } ans=0; for(int k=1;k<=m;k++) ans+=k*(g[k]-g[k-1])/g[m]; printf("%.6f\n",(double)ans); } fclose(stdin); fclose(stdout); return 0; }