题目链接: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;
}