HDU 6044

题意略。

思路:

I.对于整个区间a1,....,an,必然有一个区间[1,n]与之对应,因为a1,...,an是1,...,n的一个排列,所以在[1,n]中定然有一个最小的数字1,

如果最大的区间[l,r]长度比[1,n]小,那么我们可以知道在[l,r]之外的数字是依然大于1的,这使得1这个数字没有合法的地方可放。

II.起于1左端的区间不可能终于1的右端。

III.数字1左端的部分类似于整体,因为左端也类似地有一个最小的数字。

IV.要想知道整体的方案数有多少,假设可以由f(1,n)算出,那么f(1,n) = f(1,mid - 1) * f(mid + 1,r) * C(n - 1,mid - 1)。

V.这个题递归的顺序可以预先算出来。

#include<bits/stdc++.h>
//#pragma comment(linker,"/STACK:1024000000,1024000000")
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
const LL maxn = 1e6 + 5;

inline bool scan_d(int& ret){
    char c;int sgn;
    if(c = getchar(),c == EOF) return 0;
    while(c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while(c = getchar(),c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
} 

struct node{
    int l,r,id;
    node(int a = 0,int b = 0){
        l = a,r = b;
    }
    bool operator<(const node& nd) const{
        if(l != nd.l) return l < nd.l;
        return r > nd.r;
    }
};

int cnt;
LL fac[maxn],inv[maxn];
node store[maxn];
bool flag;

LL exgcd(LL a,LL b,LL& x,LL& y){
    if(a == 0 && b == 0) return -1;
    if(b == 0){
        x = 1,y = 0;
        return a;
    }
    LL d = exgcd(b,a % b,y,x);
    y -= a / b * x;
    return d;
}
LL rev(LL a,LL n){
    LL x,y;
    LL d = exgcd(a,n,x,y);
    if(d == 1) return (x % n + n) % n;
    else return -1;
}
void init(){
    fac[0] = 1;
    for(LL i = 1;i < maxn;++i) fac[i] = fac[i - 1] * i % mod;
    
    inv[maxn - 1] = rev(fac[maxn - 1],mod);
    for(LL i = maxn - 2;i >= 0;--i){
        inv[i] = inv[i + 1] * (i + 1) % mod;
        //printf("inv[%d] == %lld
",i,inv[i]);
    }
}
LL C(int n,int m){
    return ((fac[n] * inv[m]) % mod) * inv[n - m] % mod;
}
LL dfs(int l,int r){
    //printf("now l == %d r == %d
",l,r);
    if(flag) return 0;
    if(l > r) return 1;
    
    if(store[cnt].l != l || store[cnt].r != r){
        flag = true;
        return 0;
    } 
    node cur = store[cnt++];
    int mid = cur.id;
    LL lft = 1,rht = 1,c = 1;
    lft = dfs(l,mid - 1);
    rht = dfs(mid + 1,r);
    c = C(r - l,mid - l);
    //printf("c == %lld
",c);
    //printf("---> %lld
",(lft * rht % mod) * c % mod);
    return (lft * rht % mod) * c % mod;
}

int main(){
    int cas = 1,n;
    init();
    while(scan_d(n)){
        flag = false;
        cnt = 1;
        for(int i = 1;i <= n;++i) scan_d(store[i].l);
        for(int i = 1;i <= n;++i) scan_d(store[i].r),store[i].id = i;
        sort(store + 1,store + n + 1);
        LL ans = dfs(1,n);
        printf("Case #%d: %lld
",cas++,ans);
    }
    return 0;
}

 

原文地址:https://www.cnblogs.com/tiberius/p/8681207.html