5095: Hopscotch
题目描述
You’re playing hopscotch! You start at the origin and your goal is to hop to the lattice point (N, N). A hop consists of going from lattice point (x1, y1) to (x2, y2), where x1 < x2 and y1 < y2.
You dislike making small hops though. You’ve decided that for every hop you make between two lattice points, the x-coordinate must increase by at least X and the y-coordinate must increase by at least Y .
Compute the number of distinct paths you can take between (0, 0) and (N, N) that respect the above constraints. Two paths are distinct if there is some lattice point that you visit in one path which you don’t visit in the other.
Hint: The output involves arithmetic mod 109+ 7. Note that with p a prime like 109+ 7, and x an integer not equal to 0 mod p, then x(xp−2) mod p equals 1 mod p.
You dislike making small hops though. You’ve decided that for every hop you make between two lattice points, the x-coordinate must increase by at least X and the y-coordinate must increase by at least Y .
Compute the number of distinct paths you can take between (0, 0) and (N, N) that respect the above constraints. Two paths are distinct if there is some lattice point that you visit in one path which you don’t visit in the other.
Hint: The output involves arithmetic mod 109+ 7. Note that with p a prime like 109+ 7, and x an integer not equal to 0 mod p, then x(xp−2) mod p equals 1 mod p.
输入
The input consists of a line of three integers, N X Y . You may assume 1 ≤ X, Y ≤ N ≤ 106.
输出
The number of distinct paths you can take between the two lattice points can be very large. Hence output this number modulo 1 000 000 007 (109+ 7).
样例输入
7 2 3
样例输出
9
题目大意:给出n,x,y,从(0,0)到(n,n) 行坐标的增加每次不小于x,列坐标的增加每次不小于y。
题目分析:如果只看一维的可以把这个题看成把n个球分成t(1~n/x)份,每一份的个数都不能小于x,可以先向每一份分上x-1,就可以看成把剩下的分成t份有多少种分发,C(n-t*(x-1)-1 , t-1),这就是只看一维。
如果看成二维就是 : C(n-t*(x-1)-1 , t-1)*C(n-t*(y-1)-1 , t-1)。最后把所有结果加起来就可以。
还有一点要注意的是组合数不能直接求,要先打表,而且数很大,组合数求的时候要用到逆元。
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e6+7;
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
ll fac[maxn],inv[maxn];
ll init(){
fac[0]=1;
for (int i=1;i<maxn;i++)
fac[i]=fac[i-1]*i%mod;
inv[maxn-1]=qpow(fac[maxn-1],mod-2);
for (int i=maxn-2;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
return 0;
}
ll C(ll n,ll m){
if (n<m) return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
ll n,x,y;
init();
scanf("%lld%lld%lld",&n,&x,&y);
ll m=min(n/x,n/y);
ll ans=0;
for(ll i=1;i<=m;i++){
ans=(ans+C(n-i*(x-1)-1,i-1)%mod*C(n-i*(y-1)-1,i-1)%mod)%mod;
}
printf("%lld\n",ans);
return 0;
}