hihoCoder 1596 Beautiful Sequence 搜索
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 搜索