JZOJ 3431. 【GDOI2014模拟】网格

一天一次的规律题或组合数学题
然而这种复杂规律都有不少人能“打表可得”??
答案 \(\binom{n+m}{m}-\binom{n+m}{m-1}\)

\(Code\)

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;

LL n , m , fx[5005] , fy[5005] , ans[5005][2];

inline LL gcd(LL x , LL y){return (y == 0 ? x : gcd(y , x % y));}
inline void Mul(LL f , int x)
{
	LL g = 0;
	for(register int i = 1; i <= ans[0][x]; i++)
		ans[i][x] = ans[i][x] * f + g , g = ans[i][x] / 10 , ans[i][x] %= 10;
	while (g) ans[++ans[0][x]][x] = g , g = ans[ans[0][x]][x] / 10 , ans[ans[0][x]][x] %= 10;
}
inline void Sub()
{
	for(register int i = 1; i <= ans[0][0]; i++)
	{
		if (ans[i][0] < ans[i][1]) ans[i][0] += 10 , ans[i + 1][0] -= 1;
		ans[i][0] -= ans[i][1];
	}
	while (ans[ans[0][0]][0] == 0 && ans[0][0] > 1) --ans[0][0];
}
int main()
{
	scanf("%lld%lld" , &n , &m);
	int cnt1 = 0 , cnt2 = 0;
	for(register int i = n + m; i >= n + 1; i--) fx[++cnt1] = i;
	for(register int i = 2; i <= m; i++) fy[++cnt2] = i;
	for(register int i = 1; i <= cnt1; i++)
		for(register int j = 1; j <= cnt2; j++)
		if (fy[j] != 1)
		{
			LL d = gcd(fx[i] , fy[j]);
			fx[i] /= d , fy[j] /= d;
			if (fx[i] == 1) break;
		}
	ans[++ans[0][0]][0] = 1;
	for(register int i = 1; i <= cnt1; i++) Mul(fx[i] , 0);
	
	cnt1 = cnt2 = 0;
	for(register int i = n + m; i >= n + 2; i--) fx[++cnt1] = i;
	for(register int i = 2; i <= m - 1; i++) fy[++cnt2] = i;
	for(register int i = 1; i <= cnt1; i++)
		for(register int j = 1; j <= cnt2; j++)
		if (fy[j] != 1)
		{
			LL d = gcd(fx[i] , fy[j]);
			fx[i] /= d , fy[j] /= d;
			if (fx[i] == 1) break;
		}
	ans[++ans[0][1]][1] = 1;
	for(register int i = 1; i <= cnt1; i++) Mul(fx[i] , 1);
	Sub();
	for(register int i = ans[0][0]; i; i--) printf("%lld" , ans[i][0]);
	printf("\n");
}
posted @ 2020-08-14 16:41  leiyuanze  阅读(89)  评论(0编辑  收藏  举报