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;
}