D. Dandelion---(路径计数--组合数问题)

Dandelion

time limit per test 1.0 s
memory limit per test 256 MB
题目链接http://whu2019.contest.codeforces.com/group/YyBKO8xFiH/contest/102167/problem/D
。。。。不知道没有专用账户进不进得了了现在。。。
在这里插入图片描述
在这里插入图片描述


题目大意:给你一个坐标(x,y),计算从(0,0)到(x,y)总共有多少种走法,它可以向下和向右走,且它能走路径必须是x<y。
如图,它的路径范围就变成了这样:
在这里插入图片描述
对于这一题,它相当于组合数的问题。假设我们的方格数是完整的,那么总的路径数为C(m+n-1,m),因为有一条边是无用的,我们将这条(0,0)-(0,1)-(0,2)合并为一条,则相当于在m个竖线和n-1个横线中挑选m个或n-1个。那么总的路径就出来了:C(m+n-1,m)。

接下来的难点在于扣去非法的路径数。我们知道,一旦有路径落入空白部分则非法,那么对于m个竖线的情况又(m<n)如图,则有m-1种情况落入空白部分,所以非法路径数为:C(n+m-1,m-1).
在这里插入图片描述
那么接下来就是求组合数的问题了,为了不超时超空间,而且它的T很小,所以可以直接线性暴力(当然,就算是暴力,我们的组合数也要优化):
在这里插入图片描述
那么本层的各个点为:

c[0]=1;
for (int i=1; i<=n; i++) c[i]=c[i-1]*(n-i+1)/i;

由于要取模,所以要求i的乘法逆元:

inv[1]=1;
for (int i=2; i<=mac; i++) {
	inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}

那么本题就结束了:

#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
const int mac=1e5+5;
const int mod=1e9+7;
ll f[mac*2],inv[mac*2];
ll C(ll x,ll y);
int main()
{
	ll t,n,m;
	inv[1]=1;
	for (int i=2; i<=mac; i++){
		inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	}   
	scanf ("%lld",&t);
	while (t--){
		scanf ("%lld%lld",&m,&n);//m<n;
		ll ans=(C(m+n-1,m)-C(m+n-1,m-1)+mod)%mod;
		printf ("%lld\n",ans);
	}
	
	return 0;
}
ll C(ll x,ll y)
{
	memset(f,0,sizeof(f));
	f[0]=1;
	for (int i=1; i<=y; i++){
		f[i]=(f[i-1]*((x-i+1)*(inv[i]%mod)%mod))%mod;//求C(n+m-1,i); 
	}
	return f[y];
}

猜你喜欢

转载自blog.csdn.net/qq_43906000/article/details/89085780