您的位置:首页 > 其它

2017 多校训练第一场 HDU 6044 Limited Permutation

2017-07-27 00:19 387 查看
题意:有n个区间,对于第i个区间[li,ri]有li<=i<=ri,

对于任意1<=L<=i<=R<=n,当前仅当li<=L<=i<=R<=ri时P[i]=min(P[L],P[L+1],...,P[R])

题解:

首先要理解题意:当前仅当li<=L<=i<=R<=ri时P[i]=min(P[L],P[L+1],...,P[R])

因此对于P[i]一定有P[i]>P[li-1]且P[i]>P[ri+1],进一步说区间[li,ri](除了[1,n])一定被某个区间[lj,rj]包含,且j=li-1或j=ri+1

即区间j可分成[lj,j-1]和[j+1,rj]

我们把n个区间按L升序R降序进行排序(这样得到的区间LR正是前序遍历的区间)。得到的第1个区间一定要是[1,n](1比任何数都小),否则不合法,输出0;设这个区间对应的是第i个数,因此区间可再分为[1,i-1]和[i+1,n],看是否有这2个区间,如果没有则不合法,输出0...直到区间不可再分。

现在再来考虑方法数:设f(i)为区间i内的方法数,u,v分别为左右子区间,i内一共有ri-li+1个数,除去中间一个,要从中选i-li个数放入左区间,剩下的放入右区间,因此答案为:f(u)*f(v)*C(ri-li,i-li)
#include <bits/stdc++.h>
// #define test TEST
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+6;

typedef long long ll;
namespace IO {
const int MX = 4e7; //1e7占用内存11000kb
char buf[MX]; int c, sz;
void begin() {
c = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(int &t) {
while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
if(c >= sz) return false;
bool flag = 0; if(buf[c] == '-') flag = 1, c++;
for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
if(flag) t = -t;
return true;
}
}

typedef struct Node{
int l,r,id;
bool operator < (const Node &a) const{
if(l!=a.l) return l<a.l;
else return r>a.r;
}
}node;
node seg[maxn];
ll fac[maxn],inv[maxn];

ll Power_Mod(ll a,ll b){
ll ans=1;
while(b){
if(b&1ll){
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}

void init(){
fac[0]=1;
for(int i=1;i<maxn;i++){
fac[i]=fac[i-1]*i%mod;
}
inv[1]=1;
for(int i=2;i<maxn;i++){
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
inv[0]=1;
for(int i=1;i<maxn;i++){
inv[i]=inv[i-1]*inv[i]%mod;
}
}

ll C(ll a,ll b){
return fac[a]*inv[b]%mod*inv[a-b]%mod;
}

// void init() {
//     fac[0] = 1;
//     for (int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * i % mod;
//     inv[maxn - 1] = Power_Mod(fac[maxn - 1], mod - 2);
//     for (int i = maxn - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
// }
// ll C(ll n, ll m) {
//     ll ret = 1;
//     while (n && m) {
//         ll nn = n % mod, mm = m % mod;
//         if (nn < mm) return 0;
//         ret = ((ret * fac[nn] % mod) * inv[mm] % mod) * inv[nn - mm] % mod;
//         n /= mod, m /= mod;
//     }
//     return ret;
// }

int flag,rear;

ll dfs(int l,int r){
if(!flag) return 0;
if(l>r) return 1;
if(seg[rear].l!=l || seg[rear].r!=r){
flag=0;
return 0;
}
node now=seg[rear++];
ll ret=C(now.r-now.l,now.id-now.l)*dfs(now.l,now.id-1)%mod;
ret=(ret*dfs(now.id+1,now.r))%mod;
return ret;
}

int main(int argc, char const *argv[])
{
#ifdef test
freopen("test.txt","r",stdin);
#endif
init();
IO::begin();
int cas=1,n;
while(IO::read(n)){
for(int i=1;i<=n;i++) {
seg[i].id=i;
IO::read(seg[i].l);
}
for(int i=1;i<=n;i++)
IO::read(seg[i].r);
sort(seg+1,seg+n+1);
flag=rear=1;
printf("Case #%d: %lld\n",cas++,dfs(1,n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: