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