题意:给你一个不超过九位的不含重复数码的十进制数,每次会随机将它的数码打乱,变成一个新的数,如果它小于等于上一次的数,那么你输了;如果它大于上一次的数,那么可以继续。直到它变成能够表达的最大数为止就赢了,问你赢的概率。
设所有排列从小到大被标记为1~n。p(i)表示排列i获胜的概率。
p(n)=1;p(n-1)=1/n;p(n-2)=1/n * (1+1/n);...;p(i)=1/n * (p(n)+p(n-1)+...+p(i+1))。
递推一下就行了。
注意特判如果它已经是最大的了,输出零。
#include<algorithm> #include<cstdio> #include<vector> using namespace std; struct data{ int v,p; }t[15]; bool cmp(const data &a,const data &b){ return a.v<b.v; } vector<int> vs[15]; int T,a[15],wei,n,b[15]; double p[400000],pre[400000]; int main(){ for(int i=1;i<=9;++i){ for(int j=1;j<=i;++j){ b[j]=j; } do{ int x=0; for(int j=1;j<=i;++j){ x=x*10+b[j]; } vs[i].push_back(x); }while(next_permutation(b+1,b+i+1)); } //freopen("a.in","r",stdin); scanf("%d",&T); for(;T;--T){ wei=0; scanf("%d",&n); int tmp=n; while(tmp){ t[++wei].v=tmp%10; t[wei].p=wei; tmp/=10; } sort(t+1,t+wei+1,cmp); for(int i=1;i<=wei;++i){ a[t[i].p]=i; } int nn=0; for(int i=wei;i>=1;--i){ nn=nn*10+a[i]; } int jc=1; for(int i=1;i<=wei;++i){ jc=jc*i; } int ci=jc-(lower_bound(vs[wei].begin(),vs[wei].end(),nn)-vs[wei].begin()+1),cnt=0; p[0]=pre[0]=1.0; for(int i=1;i<=ci;++i){ p[i]=pre[i-1]/(double)jc; pre[i]=pre[i-1]+p[i]; } printf("%.9f ",ci ? p[ci] : 0.0); } return 0; }