解题思路: 题目大致可以理解为 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;
}