zoukankan      html  css  js  c++  java
  • 51NOD 1934:受限制的排列——题解

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1934

    听说会笛卡尔树的人这题都秒了啊……

    参考:https://blog.csdn.net/vectorxj/article/details/79475244

    首先题得看懂(我就是看题解才看懂题面的……),它告诉你对于i,我们有最大的(li,ri)使得这个区间内pi最小。

    于是最小的数一定是(1,n)区间内的,设为pos,那么我们只需要递归处理(1,pos-1)和(pos+1,n)的即可。

    当然我们的情况数要乘以给左区间的数的情况数。

    中途如果出现各种无解情况直接返回0即可。

    注意读入优化!

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    struct fastio{
        static const int bs=1000000;
        char c(){
        static char buf[bs],*S=buf,*T=buf;
            if(S==T){
            T=(S=buf)+fread(buf,1,bs,stdin);
            if(S==T)return EOF;
        }
        return *S++;
        }
        int operator()(){
            int X=0;char ch=c();
        if(ch==EOF)return 0;
        while(!isdigit(ch))ch=c();
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=c();
        return X;
        }
    }read;
    const int N=1e6+5;
    const int p=1e9+7;
    inline int qpow(int k,int n){
        int res=1;
        while(n){
        if(n&1)res=(ll)res*k%p;
        k=(ll)k*k%p;n>>=1;
        }
        return res;
    }
    map<int,int>mp[N];
    int n,cnt,l[N],r[N];
    int jc[N],inv[N];
    void init(int k){
        jc[0]=1;
        for(int i=1;i<=k;i++)jc[i]=(ll)jc[i-1]*i%p;
        inv[k]=qpow(jc[k],p-2);
        for(int i=k-1;i;i--)inv[i]=(ll)inv[i+1]*(i+1)%p;
        inv[0]=1;
    }
    inline int C(int a,int b){
        return (ll)jc[a]*inv[b]%p*inv[a-b]%p;
    }
    int work(int L,int R){
        if(L>R)return 1;
        int pos=mp[L][R];
        if(L==pos&&pos==R)return 1;
        if(pos<L||R<pos)return 0;
        return (ll)C(R-L,pos-L)*work(L,pos-1)%p*work(pos+1,R)%p;
    }
    int main(){
        init(1e6);
        while(n=read()){
        for(int i=1;i<=n;i++)mp[i].clear();
        for(int i=1;i<=n;i++)l[i]=read();
        for(int i=1;i<=n;i++)r[i]=read();
        bool flag=1;
        for(int i=1;i<=n;i++){
            if(mp[l[i]].count(r[i]))flag=0;
            mp[l[i]][r[i]]=i;
        }
        if(!flag)printf("Case #%d: 0
    ",++cnt);
        else printf("Case #%d: %d
    ",++cnt,work(1,n));
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    c/c++混编
    inotify监听文件
    二维数组
    CentOS7 修改系统时间
    书签书签
    c语言并行程序设计之路(四)(barrier的实现和条件变量)
    MPI分布式内存编程(一):预备知识
    有些狮子不喝咖啡:条件式与合取式的翻译
    【部分博客已搬家至博客园】对CSDN、博客园和简书的一点比较
    c语言并行程序设计之路(三)(信号量与同步)
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9176561.html
Copyright © 2011-2022 走看看