hdu6044 Limited Permutation【读入优化+dfs】

82 篇文章 0 订阅
37 篇文章 0 订阅

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6044
题意:有长度为n的序列,分别表示l[i]和r[i],然后让你构造一个a序列,a[i]满足在[l[i],r[i]]区间里面,a[i]为最小值,满足这样条件的序列有多少种
解析:首先根据题面的限定,肯定存在一个区间i是[1,n],对于这个区间,可以说第i个值已经确定了,因为这个区间是当前的整个区间,对于剩下的来说,肯定从剩下的n-1个数中选i-1个数出来填在左边,而剩下的填在右边,接下来在乘上左右区间的各自的方法数,总的计数方案应该为ans = dfs(1,i-1)*dfs(i+1,n) *C(r-l,i-l),所以需要递归往下划分,此时再往下划分的话,就会把这个区间分为[1,i-1]和[i+1,n],依次递归向下,就可以吧所有的区间扫一遍

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e6+100;
const int mod = 1e9+7;
typedef long long ll;
namespace fastIO
{
    #define BUF_SIZE 100000
    //fread -> read
    bool IOerror = 0;
    inline char nc()
    {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if (p1 == pend)
        {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if (pend == p1)
            {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch)
    {
        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
    }
    inline void read(int &x)
    {
        char ch;
        while (blank(ch = nc()));
        if (IOerror)
            return;
        for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    }
    #undef BUF_SIZE
};
using namespace fastIO;
struct node
{
    int l,r,id;
    bool operator < (const node &b)const
    {
        if(l==b.l)
            return r>b.r;
        return l<b.l;
    }
}a[maxn];
ll h[maxn];
ll qpow(ll x,ll n)
{
    ll res = 1;
    while(n)
    {
        if(n&1)
            res = res*x%mod;
        x = x*x%mod;
        n >>= 1;
    }
    return res;
}
ll C(int n,int m)
{
    ll a = h[n];
    ll b = h[m]*h[n-m]%mod;
    return a*qpow(b,mod-2)%mod;
}
int id;
ll dfs(int l,int r)
{
    if(a[id].l!=l || a[id].r!=r)
        return 0;
    int last = a[id].id;
    id++;
    ll ansl = 1,ansr = 1;
    if(l<=last-1)
        ansl = dfs(l,last-1);
    if(r>=last+1)
        ansr = dfs(last+1,r);
    return ansl*ansr%mod*C(r-l,last-l)%mod;
}
int main(void)
{
    h[0] = 1;
    for(int i=1; i<maxn; i++)
        h[i] = (h[i-1]*i)%mod;
    int n;
    int case_t = 1;
    while(read(n),!fastIO::IOerror)
    {
        for(int i=1;i<=n;i++)
            read(a[i].l);
        for(int i=1;i<=n;i++)
        {
            read(a[i].r);
            a[i].id = i;
        }
        sort(a+1,a+n+1);
        id = 1;
        ll ans = dfs(1,n);
        printf("Case #%d: %I64d\n",case_t++,ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值