[AGC025B] RGB Coloring 笔记

涉及知识点:组合数学

思路

因为涂红色的贡献是 A A A,涂蓝色的贡献是 B B B,涂绿色的贡献是 A + B A+B A+B,那么涂绿色相当与同一个格子既涂红色又涂蓝色。

我们枚举涂红色的数量 i i i,则贡献和为 A × i A \times i A×i,剩下的贡献需要用蓝色来凑,那么我们就需要 K − A × i 2 \frac{K-A\times i}{2} 2KA×i 个蓝色。

涂红色的总方案数是:
( n i ) \dbinom{n}{i} (in)
涂蓝色的总方案数是:
( n K − A × i 2 ) \dbinom{n}{\frac{K-A\times i}{2}} (2KA×in)
只需将其乘积累加即可:
∑ i = 0 n ( n i ) ( n K − A × i 2 ) \sum^{n}_{i=0}\dbinom{n}{i}\dbinom{n}{\frac{K-A\times i}{2}} i=0n(in)(2KA×in)
若一个点既涂了蓝色又涂了红色,视为涂了绿色,反之视为没涂。

AC历程

一遍过没啥好说的。

代码

#include <bits/stdc++.h>
// #pragma GCC optimize(2)
#define int long long
#define pii pair<int, int>
#define piiii pair<pii, pii>
#define il inline
#define p_q priority_queue
#define u_m unordered_map
#define bt bitset
#define rg register
#define rd Nothing::read
#define wt Nothing::write
#define endl '\n'

using namespace std;

namespace Nothing {
	il int read() {
		int f = 1, t = 0;
		char ch = getchar();
		while (ch < '0' || ch > '9') {
			if ( ch == '-' ) {
				f = -1;
			}
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9') {
			t = t * 10 + ch - '0';
			ch = getchar();
		}
		return t * f;
	}

	il void write(int x, bool s) {
		if (x < 0) {
			putchar('-');
			write(-x, false);
			return ;
		}
		if (!s && x == 0)
			return ;
		if (s && x == 0) {
			putchar('0');
			return ;
		}
		write(x / 10, false);
		putchar(x % 10 + '0');
	}
}

const int N1 = 300005;
const int N2 = 1000006;
const int Mod = 998244353;

namespace COMB {
	int fac[N2] = {0};
	void Cinit(int p) {
		fac[0] = 1;
		for (int i = 1; i < N2; i++) {
			fac[i] = fac[i - 1] * i % p;
		}
	}
	il int qpow(int a, int b, int p) {
		int ans = 1;
		while (b) {
			if (b & 1) {
				ans = ans * a % p;
			}
			a = a * a % p;
			b >>= 1;
		}
		return ans;
	}
	il int C(int n, int m, int p) {
		if (m > n || m < 0) {
			return 0;
		}
		return fac[n] * qpow(fac[m], p - 2, p) % p * qpow(fac[n - m], p - 2, p) % p;
	}
	il int Lucas(int n, int m, int p) {
		if (!m) return 1;
		return (C(n % p, m % p, p) * Lucas(n / p, m / p, p)) % p;
	}
	il int GCD(int n, int m, int p) {
		return __gcd(n, m) % p;
	}
	il int LCM(int n, int m, int p) {
		return n * m % p * qpow(GCD(n, m, p), p - 2, p) % p;
	}
}
using namespace COMB;
using namespace Nothing;

//#define debug 1
//#define multi_test 1
#define IOS 1

int T = 1;

int n, a, b, k;

void Init() {
	Cinit(Mod);
	return ;
}

void Solve() {
	cin >> n >> a >> b >> k;
	int ans = 0;
	for (int i = 0; i <= n; i++) {
		if ((k - a * i) % b == 0)
			ans = (ans + C(n, i, Mod) * C(n, (k - a * i) / b, Mod) % Mod) % Mod;
	}
	cout << ans << endl;
	return ;
}

signed main() {
#ifdef debug
	freopen("zqh.in", "r", stdin);
	freopen("zqh.out", "w", stdout);
#endif
#ifdef multi_test
	cin >> T;
#endif
#ifdef IOS
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
#endif
	while (T--) {
		Init();
		Solve();
	}
	return 0;
}
/*

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值