专栏文章
题解:P9174 [COCI 2022/2023 #4] Bojanje
P9174题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miogzmij
- 此快照首次捕获于
- 2025/12/02 19:03 3 个月前
- 此快照最后确认于
- 2025/12/02 19:03 3 个月前
通过读题可知是 dp 题,考察的是对状态的压缩,题目说 种颜色我们不能记录下每个小球的颜色,由于取球是随机的,所以位置是不重要的,我们就可以对每种颜色记录有几个,因为我们对于每种颜色具体是什么也不关心,只关心有几个球,所以可以进一步压缩。
CPPvector<vector<int>> S;
vector<int> vec;
map<vector<int>, int> mp;
void dfs(int x) {
if (x == 0) {
S.push_back(vec);
mp[vec] = S.size() - 1;
return;
}
if (vec.size() && vec.back() > x) {
return;
}
rep(i, (vec.size() ? vec.back() : 1), x) {
vec.push_back(i);
dfs(x - i);
vec.pop_back();
}
}
类似的压缩套路还有 AT_abc215_g。
然后我们按照状态转移可以拿到 sub2 36 分,拼上 sub1 就能拿到 64 分。
CPP#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = (l); i <= (int)(r); i++)
#define per(i, l, r) for (int i = (r); i >= (int)(l); i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__)
#define max(a, b) (!((a) < (b)) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
using i64 = long long;
#define int i64
const int maxn = 1000050, mod = 1e9 + 7, B = 700;
i64 power(i64 a, int b) {
i64 res = 1;
for (; b; a = (a * a) % mod, b /= 2){
if (b % 2 == 1) {
res = (res * a) % mod;
}
}
return res;
}
vector<vector<int>> S;
vector<int> vec;
map<vector<int>, int> mp;
void dfs(int x) {
if (x == 0) {
S.push_back(vec);
mp[vec] = S.size() - 1;
return;
}
if (vec.size() && vec.back() > x) {
return;
}
rep(i, (vec.size() ? vec.back() : 1), x) {
vec.push_back(i);
dfs(x - i);
vec.pop_back();
}
}
vector<int> change(vector<int> now, int a, int b) {
vector<int> to = now;
if (a == b) {
return to;
}
if (now[a] != 1) {
to[a]--;
to[b]++;
}
if (now[a] == 1) {
to[b]++;
to.erase(to.begin() + a);
}
sort(to.begin(), to.end());
return to;
}
int dp[1050][100];
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n, t, k;
cin >> n >> t >> k;
dfs(n);
dp[0][0] = 1;
int INV = power(n * n, mod - 2);
rep(i, 1, t) {
rep(j, 0, S.size() - 1) {
if (dp[i - 1][j] == 0) {
continue;
}
dp[i - 1][j] %= mod;
vector<int> st = S[j];
rep(a, 0, st.size() - 1) {
rep(b, 0, st.size() - 1) {
vector<int> nst = change(st, a, b);
dp[i][mp[nst]] += dp[i - 1][j] * st[a] % mod * st[b] % mod * INV % mod;
}
}
}
}
int ans = 0;
rep(i, 0, S.size() - 1) {
if (S[i].size() >= k) {
ans += dp[t][i];
}
}
cout << ans % mod << "\n";
return 0;
}
然后的是套路的矩阵乘法优化。
CPP#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = (l); i <= (int)(r); i++)
#define per(i, l, r) for (int i = (r); i >= (int)(l); i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__)
#define max(a, b) (!((a) < (b)) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
using i64 = long long;
#define int i64
const int maxn = 1000050, mod = 1e9 + 7;
i64 power(i64 a, int b) {
i64 res = 1;
for (; b; a = (a * a) % mod, b /= 2){
if (b % 2 == 1) {
res = (res * a) % mod;
}
}
return res;
}
vector<vector<int>> S;
vector<int> vec;
map<vector<int>, int> mp;
void dfs(int x) {
if (x == 0) {
S.push_back(vec);
mp[vec] = S.size() - 1;
return;
}
if (vec.size() && vec.back() > x) {
return;
}
rep(i, (vec.size() ? vec.back() : 1), x) {
vec.push_back(i);
dfs(x - i);
vec.pop_back();
}
}
vector<int> change(vector<int> now, int a, int b) {
vector<int> to = now;
if (a == b) {
return to;
}
if (now[a] != 1) {
to[a]--;
to[b]++;
}
if (now[a] == 1) {
to[b]++;
to.erase(to.begin() + a);
}
sort(to.begin(), to.end());
return to;
}
struct node {
int a[50][50];
int n, m;
} A, B1, B;
node mul(node a, node b) {
node c = {{}};
c.n = a.n, c.m = b.m;
rep(i, 0, a.n - 1) {
rep(j, 0, b.m - 1) {
rep(k, 0, a.m - 1) {
c.a[i][j] += a.a[i][k] * b.a[k][j] % mod;
}
c.a[i][j] %= mod;
}
}
return c;
}
int n, t, k;
void initB() {
int INV = power(n * n, mod - 2);
rep(i, 0, S.size() - 1) {
vector<int> st = S[i];
rep(a, 0, st.size() - 1) {
rep(b, 0, st.size() - 1) {
vector<int> nst = change(st, a, b);
(B.a[mp[nst]][i] += st[a] * st[b] * INV % mod) %= mod;
}
}
}
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n >> t >> k;
dfs(n);
A.n = S.size();
A.m = 1;
B.n = B.m = S.size();
initB();
A.a[0][0] = 1;
t-=1;
B1 = B;
for (; t; B1 = mul(B1, B1), t /= 2){
if (t % 2 == 1) {
B = mul(B, B1);
}
}
A = mul(B, A);
int ans = 0;
rep(i, 0, S.size() - 1) {
if ((int)S[i].size() >= k) {
ans += A.a[i][0];
}
}
cout << ans % mod << "\n";
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...