CSU 2049: 象棋

题目:

Description

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

Input

第一行一个正整数T,表示数据组数。( T<=10)
对于每组数据:一行,两个正整数N和M(N<=100000,M<=100000)。

Output

对于每组数据输出一行,代表方案数模1000000007(10^9+7)。

Sample Input

1
1 1

Sample Output

1


就是简单的计算组合数

代码:

#include
using namespace std;

const int m = 100000;
int list[m], p[9592];//9592个素数
void getp()//在p数组中存所有不超过m的素数
{
	p[0] = 2;
	int key = 0;
	for (int i = 0; i < m; i++)list[i] = i % 2;
	for (int i = 3; i < m; i += 2)if (list[i])
	{
		p[++key] = i;
		for (int j = i + i; j < m; j += i)list[j] = 0;
	}
}

int degree(int m, int p)//求m!中素数p的次数
{
	if (m)return degree(m / p, p) + m / p;
	return 0;
}

int main()
{
	getp();
	int t, n, m, mi;
	cin >> t;
	while (t--)
	{
		cin >> n >> m;
		if (n < m)n ^= m ^= n ^= m;
		long long ans = 1;
		for (int i = 0; i < 9592; i++)
		{
			mi = degree(n, p[i]) - degree(m, p[i]) - degree(n - m, p[i]);
			while (mi--)ans = ans * p[i] % 1000000007;
		}
		cout << ans << endl;
	}
	return 0;
}

你可能感兴趣的:(CSU 2049: 象棋)