1. 程式人生 > >hihoCoder 1596 Beautiful Sequence 搜索

hihoCoder 1596 Beautiful Sequence 搜索

需要 .com cout sci com gin 代碼 sca center

Beautiful Sequence

Description

對於一個正整數列a[1], ... , a[n] (n ≥ 3),如果對於所有2 ≤ i ≤ n - 1,都有a[i-1] + a[i+1] ≥ 2 × a[i],則稱這個數列是美麗的。

現在有一個正整數列b[1], ..., b[n],請計算:將b數列均勻隨機打亂之後,得到的數列是美麗的概率P。

你只需要輸出(P × (n!))mod 1000000007即可。(顯然P × (n!)一定是個整數)

Input

第一行一個整數n。 (3 ≤ n ≤ 60)
接下來n行,每行一個整數b[i]。 (1 ≤ b[i] ≤ 1000000000)

Output

輸出(P × (n!))mod 1000000007。

Sample Input

4
1
2
1
3

Sample Output

8

題意

首先定義一個序列為Beautiful為:對 2<=i<=n-1 : a[i-1]+a[i+1] >= 2*a[i]

給定n個數,問這些數的所有排列為Beautiful的有多少個

題解

由 a[i-1]+a[i+1] >= 2*a[i] 可以推導出 a[i+1]-a[i] >= a[i]-a[i-1]

也就是說構造出來的序列,兩項之差逐漸遞增

由於差可能為正數,也可能為負數

那麽順序肯定時由負數到正數

所以構造出來的序列要麽是遞減的,要麽是遞增的,要麽是先遞減隨後遞增的

事實上三種情況都可以規約為 先遞減隨後遞增 的情況,類似一個拋物線

假設現在得到了a[i],同時已知a[i-1],那麽顯然 a[i+1]>= a[i]*2-a[i-1],即補充在後的數的下界是已知的

通過搜索解決這個問題

那麽,先把所有數排個序,最小的那個數肯定就是拋物線的底部,記它有k個,總共可能構成k!個排列

然後維護四元組:<補充在左邊的數的下界,當前最左邊的數,補充在右邊的數的下界,當前最右邊的數>

遞推:考慮補充在右邊:若當前數a[now],比所求補充在右邊的數下界要大,那麽更新四元組中的後兩項分別為 2*a[now]-pre,a[now];左邊同理

然後爆完了

為了防T我還特意加了個計數項,把相同的項四元組合並了

唔折騰一晚上RE後來發現=-=請務必認真寫好排序函數 不然會哭qwq

(好久沒更博客了qwq發現我好懶

(有時候hihoCoder的題挺有意思的=-=雖然題面總給人一種硬翻國外題目的趕腳

代碼

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 //#define FUCKOJ
  4 typedef long long ll;
  5 struct Node
  6 {
  7     ll fi,se;
  8     ll pre1,pre2;
  9     ll cnt;
 10 };
 11 bool operator != (Node x,Node y)
 12 {
 13     return !((x.fi==y.fi)&&(x.se==y.se)&&(x.pre1==y.pre1)&&(x.pre2==y.pre2));
 14 }
 15 bool operator < (Node x,Node y)
 16 {
 17     if(x.fi!=y.fi)  return x.fi<y.fi;
 18     if(x.se!=y.se)  return x.se<y.se;
 19     if(x.pre1!=y.pre1)  return x.pre1<y.pre1;
 20     if(x.pre2!=y.pre2)  return x.pre2<y.pre2;
 21     return x.cnt<y.cnt;
 22 }
 23 typedef vector<Node> VEC;
 24 #define pb push_back
 25 VEC V;
 26 const ll MOD = 1e9+7;
 27 const int MAXN = 60+3;
 28 ll a[MAXN];
 29 
 30 void Run(int now)
 31 {
 32     //VEC tV(V.begin(),V.end());
 33     VEC tV;
 34     tV.clear();
 35     //V.clear();
 36     Node node1,node2;
 37     for(int i=0;i<V.size();++i)
 38     {
 39         node1=node2=V[i];
 40 
 41         if(a[now]>=node1.fi)
 42         {
 43             if(node1.pre1==0)    node1.fi=a[now];
 44             else node1.fi=a[now]+(a[now]-node1.pre1);
 45 
 46             node1.pre1=a[now];
 47             tV.pb(node1);
 48             /*if(V[i].pre1!=0)    tV.pb(node1);
 49             else if(V[i].pre2==0)
 50             {
 51                 node1.pre2=node1.se=a[now];
 52                 tV.pb(node1);
 53             }*/
 54         }
 55 
 56         if(a[now]>=node2.se)
 57         {
 58             if(node2.pre2==0)    node2.se=a[now];
 59             else node2.se=a[now]+(a[now]-node2.pre2);
 60 
 61             node2.pre2=a[now];
 62             tV.pb(node2);
 63             //if(V[i].pre2!=0)    tV.pb(node2);
 64         }
 65     }
 66     sort(tV.begin(),tV.end());
 67     V.clear();
 68     for(int i=0;i<tV.size();++i)
 69     {
 70         if(V.size()==0||(V[V.size()-1]!=tV[i]))    V.pb(tV[i]);
 71         else V[V.size()-1].cnt=(V[V.size()-1].cnt+tV[i].cnt)%(MOD);
 72     }
 73 #ifdef FUCKOJ
 74     cout<<"====="<<a[now]<<"====="<<endl;
 75     for(auto v:V)
 76     {
 77         cout<<v.fi<<" "<<v.pre1<<" "<<v.se<<" "<<v.pre2<<" "<<v.cnt<<endl;
 78     }
 79 #endif
 80 
 81 }
 82 
 83 int main()
 84 {
 85     int n;
 86     scanf("%d",&n);
 87     Node x;
 88     //x.pre1=x.pre2=x.fi=0,x.cnt=1;
 89     //x.se=0;
 90     //V.pb(x);
 91     for(int i=0;i<n;++i)
 92         scanf("%lld",a+i);
 93     sort(a,a+n);
 94     x.pre1=x.pre2=x.fi=x.se=a[0];
 95     x.cnt=1;
 96     int k=0;
 97     while(k<n&&a[k]==a[0])    k++;
 98     for(int i=1;i<=k;++i)    x.cnt=(x.cnt*i)%MOD;
 99     V.pb(x);
100     for(int i=k;i<n;++i)    Run(i);
101     ll ans=0;
102     for(auto v:V)    ans=(ans+v.cnt)%(MOD);
103     printf("%lld",(ans)%MOD);
104     return 0;
105 }


題解鏈接:http://www.cnblogs.com/scidylanpno/p/7618274.html

版權所有:scidylanpno

hihoCoder 1596 Beautiful Sequence 搜索