CF-D. AquaMoon and Chess (组合数学)

原题网址D. AquaMoon and Chess

解题思路: 题目大致可以理解为 0 所处的位置有多少种不同的状态,
可以发现当1成双的时候可以随意走,当1成单的时候, 相对于0的位置不能移动, 即不需要考虑,所以可以把题简化为双11和0 的位置的组合数学, 令 a 对 双11, b 个 0, 求得: f[a]/f[a-b]/f[b]; 但是要取模, 所以要结合逆元(除法取模即可):

// 错误代码

/*
https://codeforces.ml/contest/1546/problem/D
  D. AquaMoon and Chess
*/

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL mod = 998244353;
const int N = 2e5 + 1;
LL f[N];

void init(){ // 预处理算出阶乘 
	f[0] = 1;
	for(LL i = 1; i < N; i ++){
		f[i] = (f[i-1]*i) % mod;
	}
}

LL solve(LL a, LL b){ // C a b  求组合数
	cout << f[a] << " " << f[a-b] << " " << f[b] << endl;
	return f[a]/f[a-b]/f[b];
}
 
int main() {
	int t;
	cin >> t;
	init();
	while(t --) {
		LL n;
		cin >> n;
		string s;
		cin >> s;
		LL zero = 0; // 统计0的个数 
		LL one = 0;  // 统计双1的个数 
		for(int i = 0; i < n; i ++){
			if(s[i] == '0') zero ++;
			if(i > 0 && s[i] == '1' && s[i-1] == '1'){
				one ++; 
			}
		}
		LL  ans = solve(zero+one, one) % mod;
		cout << ans << "\n";
	}
	return 0;
}

加上除法取模 正确代码

/*
https://codeforces.ml/contest/1546/problem/D
  D. AquaMoon and Chess
*/

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL mod = 998244353;
const int N = 2e5 + 1;
LL f[N];
LL invf[N];
LL invmod(int a, int b) {
	if(b==0 || b==1) return a;
	LL k=invmod(a,b/2);
	k=(k*k)%mod;
	if(b%2) k=(k*a)%mod;
	return k;
}

void init() { // 预处理算出阶乘
	f[0] = 1;
	for(LL i = 1; i < N; i ++) {
		f[i] = (f[i-1]*i) % mod;
	}
	
	invf[200000]=invmod(f[200000],mod-2);
	for(LL i=199999; i>=0; i--) {
		invf[i]=(invf[i+1]*(i+1))%mod;
	}
}

LL solve(int a, int b){
	LL k=(f[a]*invf[b])%mod;
	k=(k*invf[a-b])%mod;
	return k;
}

int main() {
	int t;
	cin >> t;
	init();
	while(t --) {
		LL n;
		cin >> n;
		string s;
		cin >> s;
		LL zero = 0; // 统计0的个数
		LL one = 0;  // 统计双1的个数
		for(int i = 0; i < n; i ++) {
			if(s[i] == '0') zero ++;
			if(i > 0 && s[i] == '1' && s[i-1] == '1') {
				s[i] = '0';
				one ++;
			}
		}
		LL  ans = solve(zero+one, one) % mod;
		cout << ans << "\n";
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值