2017"百度之星"程序设计大赛 - 初赛(B) 1001 Chess

Chess

車是中国象棋中的一种棋子,它能攻击同一行或同一列中没有其他棋子阻隔的棋子。一天,小度在棋盘上摆起了许多車……他想知道,在一共N×M个点的矩形棋盘中摆最多个数的車使其互不攻击的方案数。他经过思考,得出了答案。但他仍不满足,想增加一个条件:对于任何一个車A,如果有其他一个車B在它的上方(車B行号小于車A),那么車A必须在車B的右边(車A列号大于車B)。

现在要问问你,满足要求的方案数是多少。
Input
第一行一个正整数T,表示数据组数。

对于每组数据:一行,两个正整数N和M(N<=1000,M<=1000)。
Output
对于每组数据输出一行,代表方案数模1000000007(1e9+7)。
Sample Input
1
1 1
Sample Output
1

思路:求组合数问题,若m>n,即为C(m,n),但是数据很大,刚开始不知道怎么求。后来发现有个公式:A/B%C=A*B^(1e9+5)%C,(网上发现的,原理我也不知道)

公式参考自博客:https://blog.csdn.net/maple_sgd/article/details/77148575

#include<iostream>
using namespace std;
typedef long long ll;
#define N 1000000007
ll qpow(ll a,ll b)
{
	ll ans=1;
	a=a%N;
	while(b)
	{
		if(b%2)
			ans=(ans*a)%N;
		a=(a*a)%N;
		b/=2;
	}
	return ans;
}
ll solve(int n,int m)
{
	ll sum1=1,sum2=1;
	for(int i=1,j=m;i<=n;i++,j--)
	{
		sum1=sum1*j%N;
		sum2=sum2*i%N;
	}
	return ((sum1%N*qpow(sum2%N,N-2)%N)%N);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m;
		scanf("%d%d",&n,&m); 
		ll ans=solve(min(m,n),max(m,n));
		cout<<ans<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43693379/article/details/88677981