1. 程式人生 > >Gym10081 A - Arcade Game -康托展開、全排列、組合數變成遞推的思想

Gym10081 A - Arcade Game -康托展開、全排列、組合數變成遞推的思想

.net 全排列 over inpu net for each problem scan different

最近做到好多概率,組合數,全排列的題目,本鹹魚不會啊,我概率論都掛科了。。。

這個題學到了一個康托展開,有點用,瞎寫一下。。。

康托展開:

適用對象:沒有重復元素的全排列。

把一個整數X展開成如下形式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0![1] 其中a[i]為當前未出現的元素中是排在第幾個(從0開始),並且0<=a[i]<i(1<=i<=n) 用來求全排列中這個串排第幾,康托展開的逆運算就是找排名第n個的是什麽。。。 傳送門,懶得寫,都差不多 1.(??ω??) 2.( ? ?ω?? )? 3.?(?????)? 4.?(?>?<?)?

直接上題目:

A - Arcade Gam

Arcade mall is a new modern mall. It has a new hammer game called "Arcade Game". In this game you‘re presented with a number n which is hanged on a wall on top of a long vertical tube, at the bottom of the tube there is a button that you should hit with your hammer.

When you hit the button with all your force (as you always do), a ball is pushed all over the tube and hit the number n

. The number n flies in the air and it‘s digits fall back in any random permutation with uniform probability.

If the new number formed is less than or equal to the previous number, the game ends and you lose what ever the new number is. Otherwise (if the number is greater than the previous number), you are still in the game and you should hit the button again.

You win if the new number formed is greater than the previous number and it is equal to the greatest possible permutation number.

Can you compute the probability of winning?

Input

The first line of the input contains the number of test cases T. Following that there are T lines represents T test cases. In each line, there is a single integer (1?≤?n?≤?109) the target number. The digits of n are all unique, which means that any 2 digits of n are different.

Output

For each test case, print one line containing the answer. Print the answer rounded to exactly 9 decimal digits.

Example

Input
3
952
925
592
Output
0.000000000
0.166666667
0.194444444

Note

In the first test case, the answer is 0 because 952 is greater than all 2,5 and 9 permutations so you can‘t win, whatever you do.

In the second test case, the answer is 0.166666667 because you may win by getting number 952 with probability 1/6.

In the third test case the answer is 0.194444444 because you may win by getting number 952 in round1 with probability 1/6 or you can win by getting number 925 in round 1 and then 952 in round 2 with probability 1/6 * 1/6.

這個題就是找出來之後求概率,這裏求概率是把符合條件的都加進去,假設10個數,每個數被跳到的概率都是1/10,為P。

假設你要求的是排名第5,那麽排名第5的跳到排名第1的有很多種跳法。可以直接跳到第一大,也可以跳2步,也可以跳3步,也可以跳4步。因為最後都是要跳到最大的,所以只求中間的步數的概率就可以,所以就是排列組合的問題,就是P*C(1,1)+P^2*C(1,3)+P^3*C(2,3)+P^4*C(3,3)。但是如果按組合數寫的話,會超時,這裏把組合數優化一下,寫成遞推就可以了,極限操作最大就是10^9,而不是(10^9+1)*10^9/2次操作。就是從n^2d的操作變成n的操作,但是遞推怎麽想呢。

抽抽一下,發現,跳1步為0,從第2大跳到第1大贏的概率就是Q1=P,從第3大開始跳獲勝的概率就是Q2=P+P*Q1=Q1*(1+P),從第4大開始跳獲勝的概率就是Q3=P+P*Q2+P*Q1=Q2*(1+P),從第5大開始跳獲勝的概率就是Q4=P+P*Q3+P*Q2+P*Q1=Q3*(1+P)。寫的亂七八糟,不知道能不能看懂。。。

代碼:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int N=1e7+10;
 8 typedef long long ll;
 9 ll fac[N];
10 bool cmp(char a,char b){
11     return a>b;
12 }
13 void jiecheng(){     //階乘
14     fac[0]=1;
15     for(int i=1;i<10;i++){
16         fac[i]=fac[i-1]*i;
17     }
18 }
19 int kangtuo(char s[],int n){    //康托展開
20     int cnt,sum;
21     sum=0;
22     jiecheng();
23     for (int i=0;i<n;++i){
24         cnt=0;
25         for(int j=i+1;j<n;++j)
26             if(s[j]<s[i])++cnt;
27         sum+=cnt*fac[n-i-1];
28     }
29     return sum;
30 }
31 char s[N];
32 double ans[N];
33 int main(){
34     int t;
35     scanf("%d",&t);
36     while(t--){
37         memset(s,0,sizeof(s));
38         scanf("%s",s);
39         int len=strlen(s);
40         int num1=kangtuo(s,len)+1;   //該數的排名,第幾大
41         //cout<<num1<<endl;
42         sort(s,s+len,cmp);
43         int num2=kangtuo(s,len)+1;   //最大的數的排名就是全排列一共多少個數
44         //cout<<num2<<endl;
45         double gailv=1.0/num2;
46         //cout<<gailv<<endl;
47         //cout<<num2-num1<<endl;
48         ans[0]=0;ans[1]=gailv;
49         for(int i=2;i<=num2-num1;i++){  //遞推
50             ans[i]=ans[i-1]*(1+gailv);
51         }
52         printf("%.9f\n",ans[num2-num1]);
53     }
54     return 0;
55 }

太智障了,好蠢啊。。。

Gym10081 A - Arcade Game -康托展開、全排列、組合數變成遞推的思想