QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#592881 | #6698. Flipping Game | PonyHex | WA | 82ms | 3728kb | C++20 | 3.9kb | 2024-09-27 09:25:30 | 2024-09-27 09:25:30 |
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 <= len; i++) {//开始设置初始状态
for (int j = 0; j <= k; j++) {
dp[i][j] = 0;
}
}
//在第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 + fj <= len; 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;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3588kb
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: 82ms
memory: 3728kb
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 5415200 0 0 39363056 323158989 236960653 346525143 996295540 321655405 0 620457800 894680933 35307363 653482343 76070089 850281292 0 0 0 821277214 20310258 980902290 372020849 491109947 122616935 189897458 0 829653170 802416651 529902608 197115509 973455563 892065178 643229903 327968684 713498522 ...
result:
wrong answer 2nd numbers differ - expected: '0', found: '5415200'