超級神題!
有n種字元,若此種字元的編號( \(1\) ~ \(n\)),\(i*2>n\),則他後面可接任意字元。若不是,則他後面接的字元編號至少要是他的兩倍。
問長度為m的字串的個數。
這道題我只想出了 \(o(n^2)\) 的做法,於是叕只能求助題解。
題解的做法和週六第二題有點像,但我並沒有分析出最長鏈的長度小於 \(log_n\) 這個性質。知道這個性質之後,就可以做了。
設 \(f[i]\) 表示長度為 \(i\) 的合法字串的個數。\(g[i]\) 表示長度為 \(i\) 的合法鏈的個數。
轉移就是
\[f[i]=\sum_^g[j]*f[i-j]
\]但 \(g[i]\) 並不能直接轉移,所以要設個輔助狀態。
設 \(p[i][j]\) 表示以 \(j\) 結尾,長度為 \(i\) 的鏈的個數,\(g[i]\) 就是 \(p[i]\) 裡合法鏈的和。
\[p[i][j]=\sum_^p[i-1][k]
\]這個可以用字首和優化,也可以將式子化簡為從 \(p[i][j-1]\) 轉移過來。
\[p[i][j]=p[i][j-1]+p[i-1][j/2]*(j\ mod\ 2==0)
\]總複雜度 \(o(m*log_n)\)。
#include using namespace std;
#define db double
#define ll long long
#define rg register
inline int gi()
const db pi = acos(-1.0);
const int n = 1e6+5, mod = 1e9+7;
int f[n],g[n],p[22][n];
int main()
} for (i=1; i<=m; ++i)
for (j=1; j<=len && j<=i; ++j)
(f[i]+=((ll)f[i-j]*g[j])%mod)%=mod;
printf("%d\n",f[m]);
return 0;
}
51nod 1196 字串的數量(DP 數論?)
這題好像是神題.v1 v2 v3分別涵蓋了51nod 5級演算法題 6級演算法題 難題 討論區的曹鵬神牛好強啊.一種做法切了v1 v2 v3,而且做法是一步一步優化的 還沒去看優化的部分,未優化已經能過v1了 設g i 為結尾編號 n 2的長度為i的合法鏈的方案數,v i 為長度為i的合法字串的方案...
51nod 1874 字串排序
定義乙個字串的無序度為所有位置後面的字母比該位置的字母小的總數之和。比如 daabec 這個字串的無序度是5,因為d後面有4個位置比它小 aabc e後面有1個比它小 c 其它位置後面沒有比自己小的。aacedgg 的無序度為1 e後面有乙個d比它小 zwqm 的無序度為6,每個位置後面所有的字母都...
51nod 1874 字串排序
1874 字串排序 基準時間限制 1 秒 空間限制 131072 kb 分值 5 難度 1級演算法題 定義乙個字串的無序度為所有位置後面的字母比該位置的字母小的總數之和。比如 daabec 這個字串的無序度是5,因為d後面有4個位置比它小 aabc e後面有1個比它小 c 其它位置後面沒有比自己小的...