BJOI2017 魔法咒語

2022-03-27 07:52:00 字數 1389 閱讀 9441

矩陣乘法+\(ac\)自動機

是道很不錯的題了

首先是前六十分,就是乙個\(ac\)自動機上的套路\(dp\),設\(dp[i][j]\)表示匹配出的長度為\(i\)在自動機上位置為\(j\)的方案數,轉移的話就列舉下乙個單詞選擇哪個放到自動機上一波匹配就好了

後面\(40\)分強行變成了另外一道題,\(l\)變成了\(1e8\),一看就是矩乘的複雜度了

但是單詞的長度都非常小,於是轉移\(dp[i][j]\)的時候只需要從\(dp[i-1]\)和\(dp[i-2]\)裡轉移,發現這非常像斐波那契的轉移,於是提前在\(ac\)機上的每個位置都處理一下對應的轉移之後矩乘就好了

**

#include#include#include#include#include#define re register

#define ll long long

#define maxn 205

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

const ll mod=1e9+7;

char s[maxn];

int fail[maxn],flag[maxn],son[maxn][26];

char t[55][maxn],len[maxn];

int n,m,l,cnt;

inline void ins()

flag[now]=1;

}inline void build()

}namespace solve1

if(flag[now]) return -1;

return now;

} inline void work()

int ans=0;

for(re int i=0;i<=cnt;i++) ans=(ans+dp[l][i])%mod;

printf("%d\n",ans); }}

namespace solve2

} inline void did_ans() }

inline void quick(int b)}

inline void work()

else if(len[j]==2)

}for(re int j=cnt+1;j<=m;j++) a[j-cnt-1][j]++;

for(re int i=0;i<=m;i++) ans[i][i]=1;

quick(l);

ll ans=0;

for(re int i=cnt+1;i<=m;i++) ans=(ans[i][cnt+1]+ans)%mod;

printf("%lld\n",ans); }}

int main()

BJOI2017 魔法咒語

題目鏈結 給 n 個基本詞彙,m 個禁忌詞語。求用基本詞彙 每個詞彙可重複詞彙 拼成長度為 l 的 不包含任何禁忌詞語的字串的方案數。在 資料規模與約定 中,我們發現可以把資料劃分成兩檔 l le 100 的 前 60pts 基本長度不超過 2 的 顯然不包含這個東西判定可以用 ac 自動機,用 m...

BJOI2017 機動訓練

落谷 loj。定義機動路徑為 相同地形序列指路徑上順序經過的地形序列。定義機動路徑的權值為相同地形序列的數量之和。求所有機動路徑的權值之和。同一類機動路徑,他的貢獻就是數量的平方 leftrightarrow 答案即本質不同機動路徑數量的平方和 leftrightarrow 即兩個人走的機動路徑形式...

BJOI2017 樹的難題

按照常規思路,選乙個點x作為分治中心,拼接x出發到子樹各點的路徑。對於拼接時兩段介面處 即x連出的那條邊,若沒有,設為0號邊 顏色為0,長度為0,到達0號兒子 顏色的影響,可以記錄每段的路徑權值 邊數以及該段的介面,將所有的路徑以介面顏色為第一關鍵字,介面編號為第二關鍵字排序。顯然,對於同一介面的路...