专栏文章
题解:P12742 [POI 2016 R3] 信使 Messenger
P12742题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minjwv6n
- 此快照首次捕获于
- 2025/12/02 03:37 3 个月前
- 此快照最后确认于
- 2025/12/02 03:37 3 个月前
建议先看 P8502。
我们考虑设 表示从 恰经过 步到 ,且不在途中经过 的方案数,就有简单的转移
每次转移完成后将 即可保证途中不经过 。
答案还要求途中不经过 ,考虑枚举不合法路径中 最后一次出现的位置 ,那么 之前只要途中不经过 即可,为 ; 后还要求途中不经过 ,于是我们设 表示从 恰经过 步回到 ,且途中不经过 的方案数,就有答案
求 时考虑枚举不合法路径中 最后一次出现的位置 , 之前还是 ,而 后要求从 到 且途中不能经过 和 ,我们惊奇地发现这恰好是 ,于是
按上述式子转移即可,时间复杂度 。注意算完 之后再清空 。
Code:
CPP#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 100 + 10, maxd = 50;
int n, m, mod, q;
int f[maxn][maxn][maxd + 10], g[maxn][maxn][maxd + 10], h[maxn][maxn][maxd + 10];
vector<int> a[maxn];
template<typename Tp_x, typename Tp_y>
inline int mod_add(Tp_x x, Tp_y y){
return x += y, x >= mod ? x -= mod : x;
}
template<typename Tp_x, typename Tp_y>
inline int self_mod_add(Tp_x &x, Tp_y y){
return x = mod_add(x, y);
}
template<typename Tp, typename... Arg>
inline int mod_add(Tp x, Arg ...args){
return x += mod_add(args...), x >= mod ? x -= mod : x;
}
int main(){
scanf("%d %d %d", &n, &m, &mod);
for (int i = 1; i <= m; i++){
int u, v;
scanf("%d %d", &u, &v), a[u].push_back(v);
}
for (int i = 1; i <= n; i++){
f[i][i][0] = h[i][i][0] = 1;
for (int j = 1; j <= n; j++){
g[i][j][0] = 1;
}
}
for (int i = 1; i <= maxd; i++){
for (int u = 1; u <= n; u++){
for (auto v: a[u]){
for (int j = 1; j <= n; j++){
self_mod_add(f[j][v][i], f[j][u][i - 1]);
}
}
}
for (int j = 1; j <= n; j++){
for (int k = 1; k <= n; k++){
h[j][k][i] = f[j][k][i], g[j][k][i] = f[j][j][i];
for (int x = 1; x < i; x++){
self_mod_add(h[j][k][i], mod - (long long)f[j][k][x] * g[k][j][i - x] % mod);
self_mod_add(g[j][k][i], mod - (long long)f[j][k][x] * h[k][j][i - x] % mod);
}
}
}
for (int j = 1; j <= n; j++){
f[j][j][i] = 0;
}
}
scanf("%d", &q);
while (q--){
int x, y, d;
scanf("%d %d %d", &x, &y, &d), printf("%d\n", h[x][y][d]);
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...