D RainbowDash 的旅行 - 第七届校赛正式赛 —— 补题
题目大意:
湖中心有一座岛,湖的外围有 m m m 间木屋(围绕小岛) ,第 i i i 间木屋和小岛之间有 a i a_i ai 座 A A A 类桥, b i b_i bi 座 B B B 类桥, A A A 桥有车可以快速通过, B B B 桥需要步行,速度稍慢。
你计划一次 n n n 天的旅行,对于每一天,你都需要从当前木屋走到小岛游玩,再走到任何一间木屋(包括出发时所在的木屋),你不想浪费时间在赶路上,于是一天通过的两座桥必须有一座是 A A A 类桥,起始在 1 1 1 号木屋,问旅行 n n n 天,有多少不同的路线组合?
1 < = n < = 1000 , 1 < = m < = 100 1<=n<=1000,1<=m<=100 1<=n<=1000,1<=m<=100
1 < = a i , b i < = 1 0 4 1<=a_i,b_i<=10^4 1<=ai,bi<=104
思路:
考虑第 i i i 间木屋到第 j j j 间木屋有多少种方法
设 f [ i ] [ j ] f[i][j] f[i][j] 表示第 i i i 间木屋到第 j j j 间木屋总方案数
如果从第 i i i 间木屋去小岛走 A A A 桥,去第 j j j 间木屋则可以走 A A A 桥或者 B B B 桥
那么方案数为 a [ i ] ∗ ( a [ j ] + b [ j ] ) a[i]*(a[j]+b[j]) a[i]∗(a[j]+b[j])
如果从第 i i i 间木屋去小岛走 B B B 桥,去第 j j j 间木屋只可以走 A A A 桥
方案数为 b [ i ] ∗ a [ j ] b[i]*a[j] b[i]∗a[j]
int f[M][M];
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
f[i][j]=a[i]*(a[j]+b[j])+b[i]*a[j];
}
}
有了第 i i i 间木屋到第 j j j 间木屋总方案数,可以考虑 1 − n 1-n 1−n 天总方案数的 d p dp dp 了
考虑第 k k k 天到达 第 1 − m 1-m 1−m 间木屋的的方案数
设 d p [ k ] [ j ] dp[k][j] dp[k][j] 表示第 k k k 天到达第 j j j 间木屋的方案数
对于第 k k k 天到达第 j j j 间木屋的方案数,
考虑由第 k − 1 k-1 k−1 天 从 i ( 1 − n ) i(1-n) i(1−n) 间木屋转移到第 j j j 间木屋的方案数: d p [ k ] [ j ] + = d p [ k − 1 ] [ i ] ∗ f [ i ] [ j ] dp[k][j]+=dp[k-1][i]*f[i][j] dp[k][j]+=dp[k−1][i]∗f[i][j]
第一天在1号木屋,所以第一天应由 d p [ 0 ] [ 1 ] dp[0][1] dp[0][1] 去转移,所以初始化 d p [ 0 ] [ 1 ] = 1 dp[0][1]=1 dp[0][1]=1
int dp[N][M];
for(int k=1;k<=n;k++){
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
dp[k][j]+=dp[k-1][i]*f[i][j];
}
}
}
最后统计第 n n n 天到达第 1 − m 1-m 1−m 间木屋总数即可
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fi first
#define se second
#define PII pair<int,int>
#define lowbit(x) x&-x
#define ALL(x) x.begin(),x.end()
const int mod = 998244353;
const int N = 100 + 10;
int f[N][N],dp[1010][N];
int a[N],b[N];
int n,m;
void solve() {
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>b[i];
}
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
f[i][j]=a[i]*(a[j]+b[j])%mod+b[i]*a[j]%mod;
f[i][j]%=mod;
}
}
dp[0][1]=1;
for(int k=1;k<=n;k++){
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
dp[k][j]+=dp[k-1][i]*f[i][j]%mod;
dp[k][j]%=mod;
}
}
}
int ans=0;
for(int i=1;i<=m;i++){
ans+=dp[n][i];
ans%=mod;
}
cout<<ans<<'\n';
}
signed main() {
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}