1. 程式人生 > >ZOJ 3929 Deque and Balls

ZOJ 3929 Deque and Balls

There are n balls, where the i-th ball is labeled as pi. You are going to put n balls into a deque. In the i-th turn, you need to put the i-th ball to the deque. Each ball will be put to both ends of the deque with equal probability.

Let the sequence (x1x2

, ..., xn) be the labels of the balls in the deque from left to right. The beauty of the deque B(x1x2, ..., xn) is defined as the number of descents in the sequence. For the sequence (x1x2, ..., xn), a descent is a position i (1 ≤ i < n) with xi
 > xi+1.

You need to find the expected value of B(x1x2, ..., xn).

Deque is a double-ended queue for which elements can be added to or removed from either the front (head) or the back (tail).

Input

There are multiple test cases. The first line of input contains an integer T

, indicating the number of test cases. For each test case:

The first line contains an integer n (2 ≤ n ≤ 100000) -- the number of balls. The second line contains n integers: p1p2, ..., pn (1 ≤ pi ≤ n).

Output

For each test case, if the expected value is E, you should output E⋅2n mod (109 + 7).

Sample Input

2
2
1 2
3
2 2 2

Sample Output

2
0
 
 
給出n個數字放入佇列中,可以放在佇列的前面也可以放在佇列的後面,問得到xi>xi+1的概率
(就是數出有多少xi>xi+1然後除以總共可能的情況),由於最後要求將所得的數字乘以2^n,
所以也就是將得到的個數乘以二就是最後答案;
這裡舉個例子
3
1 2 3
 				1
		12				21
	123		231		321		213
      (沒有)	      (31一個)       (32.21兩個)    (21一個)
總共4個,乘以2後答案是8
 
 
 
 
AC程式碼:
#include<bits/stdc++.h>  
using namespace std;  
#define mod 1000000007  
long long ans[100005];//存的是從0-當前位置,遞減數對的個數,可遞推  
  
//就是當前的可配對數,就是先前已經匹配好的*2+當前增加的  
  
long long r[100005];//記錄相同數對當前數的影響  
long long power[100005];//2的冪  
int n,t,a;  
int main()  
{  
    power[1]=1;  
    for(int i=2; i<=100000; i++)//預處理部分  
        power[i]=(power[i-1]*2)%mod;  
    cin>>t;  
    while(t--)  
    {  
        memset(ans,0,sizeof(ans));  
        memset(r,0,sizeof(r));  
        cin>>n;  
        for(int i=1; i<=n; i++)  
        {  
            cin>>a;  
            ans[i]=(ans[i-1]*2+power[i-1]-r[a]+mod)%mod;  
            //翻譯上面一行:  
            //這個狀態的可能值=上個狀態可行的對數*2(因為我這個數放下去不影響之前就匹配好的數,但是放下去有兩種可能性。  
            //                                       例如:21,然後後邊不管多少個數,這個21數對總是需要被計算進去)  
            //  
            //                +放下這個數後所有的可能性(每放下一個數,這個串就像二叉樹一樣在生長)  
            //                -相同數造成的影響(如果這個數是第一次出現,那麼總是可以放在比他大的數的右邊,同理也可以放在比他小的左邊)  
            //                  那麼這個數的對這個狀態先前的所有數都有影響。然後再後來出現這個數的時候要減去先前已經造成的影響。  
            //                  最後+mod是因為power被mod過,可能比r[a]大,(但是mod前實際是不會的)  
            //                 然後最後取模  
            //關於這個power[i-1],我再解釋下,比如21 12 ,你將要放下3,你一定可以放在一個地方使得
            //總共的xi>xi+1多一個,比如這個你可以放在21的左邊.還有12的左邊,分別會多出一個32和31.
            //這個就是power[i-1]=power[2]=2;
            //還有那個r[a]也是類似的方式去理解;
            if(i==1)  
                r[a]=(r[a]+1)%mod;  
            else  
                r[a]=(r[a]+power[i-1])%mod;  
            //cout<<ans[i]<<endl;  
        }  
        cout<<(2*ans[n])%mod<<endl;  
    }  
    return 0;  
} 
 
 
比賽的時候隊友題目翻譯錯了,我也沒有去認真讀題,於是也沒有做出來,賽後問了下學長,才稍微懂了點。
 
 
轉自http://blog.csdn.net/tinyguyyy/article/details/51133548(稍微加了點自己的的理解)