Problem Statement
在一个狭长的通道中有$n$只狼,每只狼的体积为$size_i$,如果相邻的两只狼体积不超过$m$,则可以交换位置,求可以有多少种排列。
$n≤50,1≤m≤1,000,000,000$
Tutorial
每次选出区间中体积最大的狼,如果其他狼可以越过它,那么即可在整个区间里自由移动,而不能越过它的狼则被隔离到两个区间里,可以分治。
区间总共有$n$只狼,能自由移动的狼个数为$cnt$,那么最后结果等于$$solve(l)*solve(r)*A_{n}^{cnt}$$
给定一些拓扑关系然后统计一些信息的题,算上这题最近遇到3道:
Permutation,结构是树,但因为要统计逆序对数比较烦,树形dp
局部极小值,因为是网格,而且标记的是局部极小值,所以可以通过确定较少的点状压dp计算结果
关于本题,我想到的部分
首先,可以在区间内畅通无阻的狼可以随便取一个位置
然后一个点如果两边的点都过不去,就可以分成2个子问题
因为“两边的点都过不去”这个条件并不清晰,所以我放弃了分治这个思路
正解利用了区间体积最大这个性质实现了分治
路曼曼其修远兮……
局部极小值和本题都有一个类似DAG的模型,所以我开始都试着往图论+dp的方向想==
现在我可以得到一个简洁的结论 DAG拓扑排序的结果有多少种可能 是NP问题
应该可以帮助以后少走一些弯路吧
还有关于拓扑问题的突破口其实也很简单:最值
然后就是挖性质、玩套路的本事了==
1 #include <set> 2 #include <ctime> 3 #include <queue> 4 #include <cstdio> 5 #include <bitset> 6 #include <cctype> 7 #include <bitset> 8 #include <cstdlib> 9 #include <cassert> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 #define inf (1<<30) 14 #define INF (1ll<<62) 15 #define fi first 16 #define se second 17 #define rep(x,s,t) for(register int x=s,t_=t;x<t_;++x) 18 #define per(x,s,t) for(register int x=t-1,s_=s;x>=s_;--x) 19 #define travel(x) for(int I=last[x],to;I&&(to=e[I].to);I=e[I].nxt) 20 #define prt(x) cout<<#x<<":"<<x<<" " 21 #define prtn(x) cout<<#x<<":"<<x<<endl 22 #define pb(x) push_back(x) 23 #define hash asfmaljkg 24 #define rank asfjhgskjf 25 #define y1 asggnja 26 #define y2 slfvm 27 using namespace std; 28 typedef long long ll; 29 typedef pair<int,int> ii; 30 template<class T>void nt(T x){ 31 if(!x)return; 32 nt(x/10); 33 putchar(x%10+‘0‘); 34 } 35 template<class T>void pt(T x){ 36 if(x<0)putchar(‘-‘),x=-x; 37 if(!x)putchar(‘0‘); 38 else nt(x); 39 } 40 template<class T>void ptn(T x){ 41 pt(x);putchar(‘\n‘); 42 } 43 template<class T>void pts(T x){ 44 pt(x);putchar(‘ ‘); 45 } 46 template<class T>inline void Max(T &x,T y){if(x<y)x=y;} 47 template<class T>inline void Min(T &x,T y){if(x>y)x=y;} 48 49 const int maxn=55; 50 const int mod=1000000007; 51 class NarrowPassage2 { 52 public: 53 ll cnk[maxn][maxn],fac[maxn]; 54 int m; 55 int solve(vector<int>d){ 56 if(d.size()<=1)return 1; 57 int n=d.size(); 58 int v=-1,id; 59 rep(i,0,n){ 60 if(d[i]>v){ 61 v=d[i]; 62 id=i; 63 } 64 } 65 vector<int>l,r; 66 int cnt=0; 67 rep(i,0,id){ 68 if(d[i]+v<=m)cnt++; 69 else l.pb(d[i]); 70 } 71 rep(i,id+1,n){ 72 if(d[i]+v<=m)cnt++; 73 else r.pb(d[i]); 74 } 75 return (ll)solve(l)*solve(r)%mod*cnk[n][cnt]%mod*fac[cnt]%mod; 76 } 77 int count(vector<int>d, int maximum) { 78 cnk[0][0]=fac[0]=1; 79 rep(i,1,d.size()+1) 80 fac[i]=fac[i-1]*i%mod; 81 rep(i,0,d.size()+1){ 82 rep(j,1,i)cnk[i][j]=(cnk[i-1][j-1]+cnk[i-1][j])%mod; 83 cnk[i][0]=cnk[i][i]=1; 84 } 85 m=maximum; 86 return solve(d); 87 } 88 };
时间: 2024-11-03 22:20:58