2012多校训练竞赛8 A Path Plan

链接:HDU - 6482

题意

给定x1,x2,y1,y2,求从 (0,y1) 走到 (x1,0) 和从 (0,y2) 走到 (x2,0)两路径不相交的方案数(只能往右下走)

题解

设从 (0,y) 走到 (x,0) 的路径数为 f(y,x),步数为x+y,其中向右走x次,易得f(y,x)=C_{x+y}^{x}

很容易想到容斥,方案数为f(y1,x1)*f(y2,x2)-B,B为两路径相交的方案数,

两路径相交意味着:通过交点,一定可以从 (0,y1) 走到 (x2,0),并从 (0,y2) 走到 (x1,0),

反过来,任意两条从 (0,y1) 到 (x2,0),从 (0,y2) 到 (x1,0) 的路径一定有交点(因为x1<x2,y1<y2)

所以我们证明:B=f(y1,x2)*f(y2,x1)

answer=f(y1,x1)*f(y2,x2)-f(y1,x2)*f(y2,x1)

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
#define MAXN 200005
#define mod 1000000007ll
using namespace std;
inline ll read(){
	ll x=0,f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f*=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
	return x*f;
}
ll x1,y_,x2,y2,jc[MAXN];
inline ll ksm(ll a,ll b){
	ll res=1;
	for(;b;b>>=1){
		if(b&1)res=res*a%mod;
		a=a*a%mod;
	}
	return res;
}
inline ll C(ll n,ll m){
	if(m>n)return 0;
	return jc[n]*ksm(jc[m],mod-2)%mod*ksm(jc[n-m],mod-2)%mod;
}
int main()
{
	jc[0]=1;
	for(ll i=1;i<MAXN-4;i++)jc[(int)i]=jc[int(i-1)]*i%mod;
	for(int T=read();T>0;T--){
		x1=read(),x2=read(),y_=read(),y2=read();
		printf("%lld\n",(C(x1+y_,x1)*C(x2+y2,x2)%mod-C(x1+y2,x1)*C(x2+y_,x2)%mod+mod)%mod);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43960287/article/details/108465072
今日推荐