日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【做题】SRM701 Div1 Hard - FibonacciStringSum——数学和式&矩阵快速幂

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【做题】SRM701 Div1 Hard - FibonacciStringSum——数学和式&矩阵快速幂 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接 https://www.cnblogs.com/cly-none/p/SRM701Div1C.html

題意:定義"Fibonacci string"為沒有連續1的01串。現在,給出\(a,b\),定義一個"Fibonacci string"的權值為\(x^a y^b\),其中\(x\)為0的個數,\(y\)為1的個數。

要求對所有長度為\(n\)的"Fibonacci string"的權值求和,對\(10^9 + 7\)取模。

\(n \leq 10^9, \ a, b \leq 25\)

顯然第一反應就是矩陣存下所有\((a,b)\)做快速冪。然而,這樣的話矩陣的邊長是\(O(a^2)\)的,不能通過本題。

考慮最終答案的式子:
\[ \sum_{k=0}^n {n-k+1 \choose k} k^b (n-k)^a \]
我們嘗試化簡:
\[ \begin{aligned} & \sum_{k=0}^n {n-k+1 \choose k} k^b (n-k)^a \\ = & \sum_{k=0}^n \sum_{j=0}^a {n-k+1 \choose k} k^b {a\choose j} n^{a-j} (-k)^j \\ = & \sum_{j=0}^a {a \choose j} (-1)^j \sum_{k=0}^n {n-k+1 \choose k}k^{b+j} \end{aligned} \]
注意到后面的\(\sum_{k=0}^n {n-k+1 \choose k} k^{b+j}\)就是當\(a' = 0, \ b' = b+j\)時,所有長度為\(n\)的"Fibonacci string"的權值和。這時,我們再建矩陣,邊長就只有\(O(a)\)了。最后\(O(a)\)枚舉\(j\)就能計算出答案。

時間復雜度\(O(a^3 \log n)\)

#include <bits/stdc++.h>
using namespace std;const int MOD = (int)(1e9 + 7), N = 110;
struct matrix {int n,m,mat[N][N];matrix(int n=0,int m=0): n(n), m(m) {memset(mat,0,sizeof mat);}matrix operator * (const matrix& a) const {assert(m == a.n);matrix ret = matrix(n, a.m);for (int k = 0 ; k < m ; ++ k)for (int i = 0 ; i < n ; ++ i)for (int j = 0 ; j < a.m ; ++ j)(ret.mat[i][j] += 1ll * mat[i][k] * a.mat[k][j] % MOD) %= MOD;return ret;}
};
matrix power(matrix a,int b) {assert(a.n == a.m);matrix ret = matrix(a.n, a.m);for (int k = 0 ; k < a.n ; ++ k)ret.mat[k][k] = 1;while (b) {if (b&1) ret = ret * a;a = a * a;b >>= 1;}return ret;
}
int power(int a,int b) {int ret = 1;while (b) {if (b&1) ret = 1ll * ret * a % MOD;a = 1ll * a * a % MOD;b >>= 1;}return ret;
}
class FibonacciStringSum {
public:int get( int n, int a, int b ) ;
};
int val[N],cmb[N][N];
int FibonacciStringSum::get(int n, int a, int b) {memset(cmb,0,sizeof cmb);for (int i = 0 ; i <= a + b ; ++ i)cmb[i][0] = 1;for (int i = 1 ; i <= a + b ; ++ i)for (int j = 1 ; j <= i ; ++ j)cmb[i][j] = (cmb[i-1][j] + cmb[i-1][j-1]) % MOD;matrix sta = matrix(1, 2 * (a + b + 1));matrix tran = matrix(2 * (a + b + 1), 2 * (a + b + 1));sta.mat[0][0] = 1;for (int i = 0 ; i <= a + b ; ++ i) {tran.mat[i][i] = 1;tran.mat[i + a + b + 1][i] = 1;for (int j = 0 ; j <= i ; ++ j)tran.mat[j][a + b + 1 + i] += cmb[i][j];}tran = power(tran, n);sta = sta * tran;for (int i = 0 ; i <= a + b ; ++ i)val[i] = (sta.mat[0][i] + sta.mat[0][i + a + b + 1]) % MOD;int ans = 0;for (int i = 0, t = 1 ; i <= a ; ++ i, t = -t)(ans += 1ll * t * cmb[a][i] * power(n, a - i) % MOD * val[b + i] % MOD) %= MOD;ans = (ans % MOD + MOD) % MOD;return ans;
}


小結:這個問題的特殊之處在于,既可以直接矩陣快速冪,也可以寫成數學和式。然而,二者都不能直接解決這個問題。把兩種方法相結合一直是常用的技巧(如分塊),在這里也啟示我們對于一個問題不能死板地但從一個方向來思考。

轉載于:https://www.cnblogs.com/cly-none/p/SRM701Div1C.html

總結

以上是生活随笔為你收集整理的【做题】SRM701 Div1 Hard - FibonacciStringSum——数学和式&矩阵快速幂的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。