51nod1934:受限制的排列 (分治+组合数)

对于一个  11 到  nn 的排列  p1,p2,,pnp1,p2,⋯,pn ,我们可以轻松地对于任意的  1in1≤i≤n 计算出  (li,ri)(li,ri) ,使得对于任意的  1LRn1≤L≤R≤n 来说  min(pL,pL+1,,pR)=pimin(pL,pL+1,⋯,pR)=pi 当且仅当  liLiRrili≤L≤i≤R≤ri 。 

给定整数  nn 和  (li,ri)(li,ri)   (1in)(1≤i≤n) ,你需要计算有多少种可能的  11 到  nn 的排列  p1,p2,,pnp1,p2,⋯,pn 满足上述条件。 

由于答案可能很大,你只需要给出答案对  109+7109+7 取模的值。

 

Input每个测试点包含多组测试数据,不超过 5000 组。 
对于每组测试数据: 
第一行包含一个正整数 n ,满足 1 ≤ n ≤ 10^6 。 
第二行包含 n 个正整数 l_1, l_2, ..., l_n ,对于 i = 1, 2, ..., n 满足 1 ≤ l_i ≤ i 。 
第三行包含 n 个正整数 r_1, r_2, ..., r_n ,对于 i = 1, 2, ..., n 满足 i ≤ r_i ≤ n 。 
保证每个测试点的所有测试数据的 n 之和不超过 3*10^6 。 
每个测试点的输入数据不超过 40MiB ,请做好读入优化。Output对于每组测试数据,输出一行"Case #x: y"(不含引号),其中 x 表示测试数据的编号(从 1 开始), y 表示这组数据的答案对 10^9+7 取模的值。Sample Input

3
1 1 3
1 3 3

Sample Output

Case #1: 2

思路:用solve(L,R)表示当前区间的排列方案数,显然最大的一个数贯穿整个区间,不难找到这个最大的数的位置pos,那么把最大的数安置在pos位置处,然后挑选pos-L个数到pos的左边,剩下的到右边,变为solve(L,pos-1)*solve(pos+1,R);

(这里用map来找最大位置。普通的输入优化还是TEL

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int Mod=1e9+7;
const int maxn=1000000;
int L[maxn+10],pre[maxn+10],lat[maxn+10];
int fac[maxn+10],rev[maxn+10],ans,N,Case=0;  ;
map<pair<int,int>,int >mp;
void read(int &x){
    x=0; char c=getchar();
    while(c>'9'||c<'0') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
}
void solve(int l,int r)
{
    if(l>r) return ;
    int pos=mp[make_pair(l,r)];
    if(pos>r||pos<l){ ans=0; return ;}
    ans=(ll)ans*fac[r-l]%Mod*rev[pos-l]%Mod*rev[r-pos]%Mod;
    solve(l,pos-1); solve(pos+1,r);
}
int main()
{    
     
     fac[0]=1; for(int i=1;i<=maxn;i++) fac[i]=(ll)fac[i-1]*i%Mod;
     rev[1]=1; for(int i=2;i<=maxn;i++) rev[i]=(ll)(Mod-Mod/i)*rev[Mod%i]%Mod;
     rev[0]=1; for(int i=2;i<=maxn;i++) rev[i]=(ll)rev[i-1]*rev[i]%Mod;
     while(~scanf("%d",&N)){
         ans=1; mp.clear();
         for(int i=1;i<=N;i++) read(pre[i]);     
        for(int i=1;i<=N;i++) read(lat[i]);
        for(int i=1;i<=N;i++) mp[make_pair(pre[i],lat[i])]=i;
        solve(1,N);
        printf("Case #%d: %d\n",++Case,ans);
     }
     return 0;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/9184982.html