Codeforces Round 925 (Div. 3)G. One-Dimensional Puzzle 组合数,隔板法,允许有空的先欠做法

Problem - G - Codeforces

当然得先分析题目的情况

类型1,2的数量差不能大于1:

样例3失败解释:

4 6 100 200

第六个型号2是没法再放进去的,所以可以分析出 类型1与类型2之间的差不能超过1

类型3,4可以自己拼自己;

3可以在1 2间,4 在2 1间:

1 2可以拼在一起,也可以在1 2 之间插入若干个3。

4同理。

所以题目问有多少种情况。

当1,2数目不同时:

//  1   2   1
//4   3   4   3  
//  2   1   2
//3   4   3   4

(设a,b,c,d分别是1,2,3,4类型的数目)

可以看出对3和4来说可以插入的位置数目是相同的,为max(a,b)

那么问题等价于若干个盒子,我们把一对球放入盒子中,有多少种放法。(3和4的方法互补干扰,放法之积即为答案。)

而且1 2 之间可以为空,“隔板法”去放3是不行的(隔板法把n个分成若干份,每份至少为1个)。

比如c个球放入a个盒子,这里我们可以先欠做法:

先欠做法:

我们放c+a个球,最后每个盒子取1个,不就把这a个取出来了吗。

这种就等价于c个球放入a个盒子,允许有空

当1,2数目相同时:

// 1 2 1 2
//4 3 4 3 4 
// 2 1 2 1 
//3 4 3 4 3  

要么3多一个,要么4多一个,两种情况加起来即可,同上做法。

代码:

注意阶乘要开到2e6,因为c虽然最大为1e6,但是我们先欠做法计算的是c + gap

ll a[2000005];
ll ksm(int x, int y, int mod) {
	if (x == 1) return 1;
	ll res = 1, base = x;
	while (y) {
		if (y & 1) res = (res * base) % mod;
		base = (base * base) % mod;
		y >>= 1;
	}
	return res;
}

ll C(ll n, ll m, ll p)
{
	if (m > n)return 0;
	return ((a[n] * ksm(a[m], p - 2, p)) % p * ksm(a[n - m], p - 2, p) % p);
}

void solve()
{
	int a, b, c, d;
	cin >> a >> b >> c >> d;
	if (abs(a - b) > 1 || a == 0 && b == 0 && c!=0&& d!=0)
	{
		cout << 0 << endl;
		return;
	}
	if (a == 0&&b==0)
	{
		if (c == 0 || b == 0)
			cout << 1 << endl;
		else
			cout << 0 << endl;

		return;
	}


	//
	int ans = 0;
	int gap = max(a, b);
	if (a == b)
	{
		ans = (C(c + gap, gap, mod) * C(d + gap - 1, gap - 1, mod) % mod 
			+ C(c + gap - 1, gap - 1, mod) * C(d + gap, gap, mod) % mod)%mod;
	}
	else
	{
		ans = C(c + gap - 1, gap-1, mod) * C(d + gap - 1, gap-1, mod) % mod;
	}
	cout << ans << endl;
}
signed main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	a[0] = a[1] = 1;
	for (int i = 2; i <= 2000000; i++)
	{
		a[i] = a[i - 1] * i%mod;
	}
	int t = 1;
	cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值