組合數計算【JZOJ】

DescriptionDescription

計算組合數

InputInput

第一行爲一個整數T (1 <= T <= 10),表示測試數據組數。
接下來T行,每行有兩個數,分別爲n和m。

OutputOutput

對於每一對n和m,輸出C(n, m)的值。每組數據各佔一行。

SampleSample InputInput

2
4 2
5 3

SampleSample OutputOutput

6
10

TrainTrain ofof ThoughtThought

直接暴力
高精壓位

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ull unsigned long long
#define INF 10000
using namespace std;
ull n, m, l, ll, r, rr, Ans;
ull A[INF + 250];
int T;
void Mud(ull x, ull y, ull &z)
{
	A[INF] = 1;
	for(ull i = x + 1; i <= y; ++i)
	{
		ull t = i; 
		while(z && !(i % z))t /= z--;
		ull g = 0;
		for(int j =INF; j >= 1; j--)
		{
			A[j] = A[j] * t + g;
			g = A[j] / (ull)1e9;
			A[j] %= (ull)1e9;
		}
	}
}
void Div(ull k)
{
	for(ull i = 2; i <= k; i++)
	{
		ull g = 0, h = 0, t = 1;
		while(t <= INF && !A[t])
			t++;t--;
		while(++t && t <= INF)
		{
			A[t] += g;
			g = (A[t] % i) * (ull)1e9;
			A[t] /= i;
		}
	}
}
int main()
{
	scanf("%d", &T);
	while(T--)
	{
		memset(A, 0 ,sizeof(A));
		scanf("%llu%llu", &n, &ll);
		if((n - ll == (ull)1) || (ll == 1))
		{printf("%llu\n", n);continue;}
		if((n == ll) || !(ll))
		{printf("1\n");continue;}
		
		rr = n - ll;
		l = max(ll, rr), r = min(ll, rr);
		Mud(l, n, r);
		Div(r);
		int t = 1;
		while(t <= INF && !A[t])
			t++;
		printf("%d", A[t]);
		while(++t <= INF)
		{
			if(A[t] < 1e8)printf("0");
			if(A[t] < 1e7)printf("0");
			if(A[t] < 1e6)printf("0");
			if(A[t] < 1e5)printf("0");
			if(A[t] < 1e4)printf("0");
			if(A[t] < 1e3)printf("0");
			if(A[t] < 1e2)printf("0");
			if(A[t] < 1e1)printf("0");
			printf("%llu", A[t]);
		}
		printf("\n");
	}
	return 0;
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章