Hopscotch
时间限制: 5 Sec 内存限制: 128 MB题目描述
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
提示
题意:从(0,0)处出发,走到目的地(n,n)。每走一步在x轴方向最少移动X距离,在y轴方向最少移动Y距离。求走到目的地的方案数。
解题过程:
刚开始想dp,但是数据范围比较大,就像通过一维DP实现二维操作,后来想了想不会……后来,发现好像能用组合数来做。就不断找组合数的公式,在推爆了好多次之后,选择分类讨论各种情况…但是各种RE。在老师标程中才了解了组合数公式——C(n-k*x+k-1,k-1)*C(n-k*y+k-1,k-1)。我们从1枚举到n/max(X,Y),并求和取模。
求和过程大致如下:
ll ans=0;
for (int i=1;i<=t;i++){
if(n-i*x+i-1<i-1||n-i*y+i-1<i-1) continue;
ans+=C(n-i*x+i-1,i-1)*C(n-i*y+i-1,i-1)%mod,ans%=mod;
// cout<<i<<" "<<ans<<endl;
}
过题代码如下:
#include <cstdio>
#include <cstring>
#include <functional>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=1e6+10;
const int mod = 1e9+7;
typedef long long ll;
ll Pow_mod(ll a,ll n){ll res=1;while(n){if(n&1)res=res*a%mod;a=a*a%mod;n>>=1;}return res;}
ll fac[maxn];
void init(){
fac[0]=1;
for (int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
}
ll C(ll n,ll m){
return fac[n]*Pow_mod(fac[n-m]*fac[m]%mod,mod-2)%mod;
}
int main(){
init();
ll n,x,y;cin>>n>>x>>y;
ll t=n/max(x,y);
ll ans=0;
for (int i=1;i<=t;i++){
if(n-i*x+i-1<i-1||n-i*y+i-1<i-1) continue;
ans+=C(n-i*x+i-1,i-1)*C(n-i*y+i-1,i-1)%mod,ans%=mod;
// cout<<i<<" "<<ans<<endl;
}
cout<<ans<<endl;
return 0;
}
其实在推组合数公式的过程中要保持冷静……不能老是思维爆炸……
蒟蒻求大犇轻喷……