zoj——3624 Count Path Pair

Count Path Pair

Time Limit: 3 Seconds      Memory Limit: 65536 KB

You are given four positive integers m,n,p,q(p < m and q < n). There are four points A(0,0),B(p,0),C(m,q),D(m,n). Consider the path f from A to D and path g from B to Cf and g are always towards and parallel to the positive direction of one axis, and they can only change their direction on integer points(whose coordinates are both integers).

You are asked to count the number(mod 100000007) of pair (f,g) that and g have no intersection.

Input

There are multiple cases(less than 100). Each case is a line containing four integers m,n,p,q(m ≤ 100000 and n ≤ 100000).

Output

For each case, output a single line containing the right answer.

Sample Input
2 2 1 1
3 2 1 1
Sample Output
3
6

 

题目大意:从A到D与从B到C的路径中不相交的有多少条。

思路:

这道题比较恶心,读题目大约找了2位大佬读,看了大约有1个多小时才搞懂的题意。(ORZ)

唉。这道题我们要求不相交的条数,不过不想交直接求太复杂,所以转化为补集思想:不想交=所有-相交,我们求出相交的,然后用总条数减去相交的条数就好了!

但是问题来了,我们要怎样求总条数与相交的条数呢?!

总路径数是C(M+N,M)*C(Q+M-P,Q)。

然后相交的地方肯定是B与C构成的矩形当中。

我们可以考虑A到C以及B到D,他们的路径必定有相交的,而且相交的位置必定也在矩形当中。

而且相交之后你可以考虑成从A到C的路径改为从交点到D,就样就完成了转化。

结果便是C(M+N,M)*C(Q+M-P,Q)-C(N+M-P,N)*C(M+Q,M);(为什么,背公式!)

然而,这还不够,因为这道题让着取模啊!!!(靠,变态的题目、、、、、、)

没办法,还是要搞一搞的,据学长说在遇到排列组合取模的问题的时候可以求乘法逆元(模数为质数)(还记不记得我们之前在做乘法逆元的题的时候遇到过这样的题,这里粘一下那道题:http://www.cnblogs.com/z360/p/7327322.html)我们这里上公式:

(a/b)mod p=a*c mod p = (a mod p * c mod p)mod p(定义 c为b在mod p意义下的逆元)

这个地方好像可以用卢卡斯定理做、、、、、(然而蒟蒻并不会,做完这道题再学吧、、、、、、、(⊙o⊙)…)

好了,好像这样就差不多了。(然而蒟蒻表示做了一天啊!~~~~(>_<)~~~~)

mdzz 取模的地方写错了,硬是找了一天、、、、、

代码:

 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1000005
#define mod 100000007  
#define ll long long 
using namespace std;
ll ans,m,n,q,p,jie[N];
ll read()
{
    ll x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
ll ins(ll n)
{
    jie[0]=1;
    for(ll i=1;i<n;i++)
     jie[i]=(jie[i-1]*i)%mod;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    ll r=exgcd(b,a%b,x,y),tmp;
    tmp=x,x=y,y=tmp-a/b*y;
    return r;
}
ll c(ll a,ll b)
{
    ll sum;
    ll x,y;b=jie[b]%mod*jie[a-b]%mod;
    sum=jie[a]; 
    exgcd(b,mod,x,y);
    x=(mod+x%mod)%mod;
    sum=(sum%mod*x%mod)%mod;
    return sum;
}
int main()
{
    ins(N);
    while(~scanf("%lld",&m))
    {
        n=read(),p=read(),q=read();
        ans=((c(m+n,m)%mod*c((q+m-p),q)%mod)%mod-(c((n+m-p),n)%mod*c((m+q),m)%mod)+mod)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/z360/p/7355144.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值