A - Arcade Game Gym - 100814A (概率思维题)
题目链接:https://cn.vjudge.net/contest/285964#problem/A
题目大意:每一次给你你一个数,然后对于每一次操作,可以将当前的数的每一位互换,如果互换后的数小于等于原来的数,那么停止操作,如果大于原来的数,则继续操作,到达当前这些数字能租成的最大的数的时候停止,然后问你能组成最大的数概率是多少?
具体思路:对于当前的数,我们先计算出这个比这个数大的有多少个,这个过程可以通过全排列的函数来进行计算。然后再计算一下当前的位数能构成的数的个数是多少,然后就开始求概率了。假设比当前的数大的有三个,那么概率计算就是 C(2,0)*(1/3)+C(2,1)*(1/3)*(1/3)+C(2,2)*(1/3)*(1/3)*(1/3).解释一下为什么是C(2,1),我们假设当前的关系是1>2>3,对于1,我们既可以通过2跳过去,还可以通过3跳过去,所以是C(2,1)。然后再开始化简式子(直接组合数会超时,,)对于上面的式子,我们把(1/3)提取出来,然后就变成了(1/3)*(1+2*(1/3)+(1/3)*(1/3)),然后就是(1/q)*(1+1/q)^(n-1).
AC代码:
1 #include<iostream> 2 #include<cmath> 3 #include<stdio.h> 4 #include<algorithm> 5 using namespace std; 6 # define ll long long 7 const int maxn = 2e4+100; 8 int f[maxn]; 9 int a[maxn]; 10 int main(){ 11 // cout<<(1.0/6.0)*(1.0+1.0/6.0)<<endl; 12 int T; 13 f[1]=1; 14 for(int i=2;i<=10;i++){ 15 f[i]=f[i-1]*i; 16 } 17 scanf("%d",&T); 18 while(T--){ 19 int n; 20 scanf("%d",&n); 21 int num=0; 22 while(n){ 23 a[++num]=n%10; 24 n/=10; 25 } 26 for(int i=1;i<=num/2;i++){ 27 swap(a[i],a[num-i+1]); 28 } 29 int ans=0; 30 while(next_permutation(a+1,a+num+1)){ 31 ans++; 32 } 33 if(ans==0){ 34 printf("0.000000000\n"); 35 continue; 36 } 37 double tot=1.0/(f[num]*1.0); 38 //cout<<f[num]<<endl; 39 double d=1.0/(f[num]*1.0); 40 double tmp=1.0+d; 41 //cout<<tmp<<" "<<tot<<endl; 42 for(int i=1;i<ans;i++){ 43 tot=tot*tmp; 44 } 45 printf("%.9lf\n",tot); 46 } 47 return 0; 48 }