QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#592910 | #6698. Flipping Game | PonyHex | WA | 84ms | 3808kb | C++20 | 3.9kb | 2024-09-27 09:46:55 | 2024-09-27 09:46:58 |
Judging History
answer
#define _CRT_SECURE_NO_WARNINGS 1
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define ll long long
//#define double long double
#define lc u<<1
#define rc u<<1|1
#define X first
#define Y second
#define endl "\n"
#define int long long
const int N = 2e5 + 50;
const int M = 5e5 + 5;
const ll maxm = 1e18 + 5;
const ll mod = 998244353;
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
//random_shuffle(id + 1, id + n + 1);
ll ksm(ll a, ll b);
ll gcd(ll a, ll b);
template<class T>inline void read(T& x) {
x = 0;
char c = getchar();
while (!isdigit(c))c = getchar();
while (isdigit(c))x = x * 10 + (c & 15), c = getchar();
}
void write(ll x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
return;
}
ll len, k, m;
string str, demo;
ll dp[105][105];
ll f[105];
ll inv[105];
ll C(ll base, ll u) {
if (u == base || u == 0ll)return 1;
//cout << u << " " << base << endl;
//cout << f[base] << " " << inv[base - u] << " " << inv[u] << endl;
ll ans = 1; ans = (f[base] * inv[base - u]) % mod * inv[u] % mod;
return ans % mod;
}
void solve()
{
//我感觉是组合数学,但是我又不知道怎么搞出来
//首先有必须操作的元素,在进行必要的操作后,剩余的操作已经是任选元素,操作偶数次,只要合法(在同一次操作没有两个相同元素)
//是否可以使用总情况减出来?,总情况的话,应为Cn,m*k,这样就是所有的情况,不合法,就是对给出的任意需要操作奇次的元素,操作偶次
//但是这样的情况数依然非常多
//dp?好多dP的题我看不出来是dp,
//感觉自己想想不出来,看了题解思路才有感觉,要想正确的转移到最终状态,最终状态的特质有0,1的个数,但是不对,因为还有位置
//如果数据较小我就用状压来储存状态了,但是100开不出来,所以状态的设置不能携带0,1,的具体位置
//那么状态就不应该是0,1的个数,然后题解使用了一种状态,在第k轮与最终状态对应位置元素不同的个数
//这样就很对了,每次选择相同的元素修改,不同的元素修改,和为m,枚举情况即可
//感觉一般组合数学会经常和dp连接起来,或者dfs,
//忘取mod,嘶,t了,C得预处理出来
cin >> len >> k >> m;
cin >> str >> demo;
for (int i = 0; i <= k; i++) {//开始设置初始状态
for (int j = 0; j <= len; j++) {
dp[i][j] = 0;
}
}
//memset(dp, 0, sizeof(dp));
//在第0轮,不同的元素个数直接统计即可
ll num = 0;
for (int i = 0; i < len; i++) {
if (str[i] != demo[i])num++;
}
dp[0][num] = 1;
for (int i = 1; i <= k; i++) {//枚举轮次
for (int fj = 0; fj <= len; fj++) {//枚举过去的状态,不同元素的个数
for (int j = 0; j<=m; j++) {//枚举要得到的不同元素的个数
ll val = m - j;//要修改的相同元素的个数
if (val < 0)continue;
if (len - fj < j)continue;
if (fj < val)continue;
//cout << i << " " << fj + j - val << " " << i - 1 << " " << fj << endl;
//cout << dp[i - 1][fj] * C(len - fj, j) * C(fj, val) << endl;
dp[i][fj + j - val] += ((dp[i - 1][fj] * C(len - fj, j)) % mod) * C(fj, val)%mod;
dp[i][fj + j - val] % mod;
}
}
}
cout<<dp[k][0]%mod<<endl;
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
f[0] = 1;
for (int i = 1; i <= 100; i++) {
f[i] = i*f[i - 1]; f[i] %= mod;
inv[i] = ksm(f[i], mod - 2);
}
int T = 1;
cin >> T;
//read(T);
while (T--)
solve();
return 0;
}
/*PonyHex*/
ll ksm(ll a, ll b) {
ll base = a;
ll ans = 1;
while (b) {
if (b & 1)ans *= base % mod;
ans %= mod;
base *= base; base %= mod;
b >>= 1;
}
return ans % mod;
}
ll gcd(ll a, ll b) {
return b ? gcd(b, a % b) : a;
}
详细
Test #1:
score: 100
Accepted
time: 0ms
memory: 3652kb
input:
3 3 2 1 001 100 3 1 2 001 100 3 3 2 001 100
output:
2 1 7
result:
ok 3 number(s): "2 1 7"
Test #2:
score: -100
Wrong Answer
time: 84ms
memory: 3808kb
input:
1000 8 50 2 11111001 01100001 13 4 5 0010011001101 0000001010010 15 58 12 011111110110100 011010000101000 15 30 2 000101100111101 100010100110000 16 99 15 0111011010111101 1000100101011100 7 73 1 0010010 1010111 1 45 1 1 1 15 64 4 111000001000100 111000110011011 13 16 6 0000001101000 0101001010111 5...
output:
0 0 0 0 0 565123576 0 671397628 866048220 0 0 0 934159397 0 0 0 657964873 0 0 0 297620792 518284447 16636231 1 294524820 259008109 0 0 0 0 0 0 990349196 899244686 0 0 497963164 0 49814547 0 0 0 0 0 529815127 411739397 562040211 0 0 0 0 0 0 0 531433326 0 77531359 703399699 0 0 0 1 0 896329183 0 0 0 0...
result:
wrong answer 901st numbers differ - expected: '295081541', found: '705092493'