原文链接 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;
}

小结:这个问题的特殊之处在于,既可以直接矩阵快速幂,也可以写成数学和式。然而,二者都不能直接解决这个问题。把两种方法相结合一直是常用的技巧(如分块),在这里也启示我们对于一个问题不能死板地但从一个方向来思考。

【做题】SRM701 Div1 Hard - FibonacciStringSum——数学和式&矩阵快速幂的更多相关文章

  1. [ An Ac a Day ^_^ ] hdu 4565 数学推导+矩阵快速幂

    从今天开始就有各站网络赛了 今天是ccpc全国赛的网络赛 希望一切顺利 可以去一次吉大 希望还能去一次大连 题意: 很明确是让你求Sn=[a+sqrt(b)^n]%m 思路: 一开始以为是水题 暴力了 ...

  2. 2018.09.26 bzoj5221: [Lydsy2017省队十连测]偏题(数学推导+矩阵快速幂)

    传送门 由于没有考虑n<=1的情况T了很久啊. 这题很有意思啊. 考试的时候根本不会,骗了30分走人. 实际上变一个形就可以了. 推导过程有点繁杂. 直接粘题解上的请谅解. 不得不说这个推导很妙 ...

  3. BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )

    BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位. 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理 ...

  4. [HNOI2011]数学作业 矩阵快速幂 BZOJ 2326

    题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 NNN 和 MMM ,要求计算Concatenate(1..N) Concatenate (1 .. N) ...

  5. 51nod 1242 斐波那契数列的第N项——数学、矩阵快速幂

    普通算法肯定T了,所以怎么算呢?和矩阵有啥关系呢? 打数学符号太费时,就手写了: 所以求Fib(n)就是求矩阵  |  1  1  |n-1  第一行第一列的元素. |  1  0  | 其实学过线代 ...

  6. Codeforces Round #362(Div1) D Legen...(AC自动机+矩阵快速幂)

    题目大意: 给定一些开心串,每个串有一个开心值,构造一个串,每包含一次开心串就会获得一个开心值,求最大获得多少开心值. 题解: 首先先建立AC自动机.(建立fail指针的时候,对val要进行累加) 然 ...

  7. 刷题总结—— Scout YYF I(poj3744 矩阵快速幂+概率dp)

    题目: Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate int ...

  8. hdu 5171 GTY's birthday gift(数学,矩阵快速幂)

    题意: 开始时集合中有n个数. 现在要进行k次操作. 每次操作:从集合中挑最大的两个数a,b进行相加,得到的数添加进集合中. 以此反复k次. 问最后集合中所有数的和是多少. (2≤n≤100000,1 ...

  9. (中等) CF 576D Flights for Regular Customers (#319 Div1 D题),矩阵快速幂。

    In the country there are exactly n cities numbered with positive integers from 1 to n. In each city ...

随机推荐

  1. js对重复数组去重

    var arr=[1,1,1,1,2,2,2,3,3,4,1,4,5,7,8,7,7] let m = {} arr.filter(item => m[item] >= 1 ? false ...

  2. 2019-04-25t16:19:49 转成正常的年月日

    1.首先得到的值时2019-04-25t16:19:49 2.想转成2019-04-25 3. var d = new Date(2019-04-25t16:19:49); var yy = d.ge ...

  3. spring boot错误: 找不到或无法加载主类

    一:当在eclipse启动spring boot项目时出现问题: springboot错误: 找不到或无法加载主类 解决办法: 1,通过cmd命令行,进入项目目录进行,mvn clean instal ...

  4. redis 3.2 新数据结构:quicklist、String的embstr与raw编码方式分界点

    Redis3.2.0引入了新的quicklist的数据结构做了list的底层存储方案.废弃了原来的两个配置参数, list-max-ziplist-entries list-max-ziplist-v ...

  5. struct ifreq学习和实例

    一.struct ifreq结构体 这个结构定义在/usr/include/net/if.h,用来配置和获取ip地址,掩码,MTU等接口信息的. /* Interface request struct ...

  6. 关于SSD Trim功能

    TRIM指令是微软联合各大SSD厂商所开发的一项技术,属于ATA8-ACS规范的技术指令.   TRIM是告诉NAND闪存固态存储设备要擦除哪些数据的SATA接口指令.当相关页面的数据可以被覆盖时,操 ...

  7. MyEclipse破解步骤

    1.下载安装(注:安装后不要打开myeclipse,以下步骤完成方可打开) 2.解压破解文件 3.打开文件夹patch 3.全部复制 4.找到myeclipse的安装目录,打开plugins文件夹 5 ...

  8. #WEB安全基础 : HTTP协议 | 0x15 HTTPS:给你点颜色看看

    "你好,我是HTTPS,我只是披了个外壳,我还是原来的HTTP." 这是HTTPS叫我转达给你的话. HTTPS本质上就是HTTP,只不过加了点调料.它比HTTP更安全,使用了加密 ...

  9. day13 python迭代器与生成器

    迭代器 字符串.列表.元组.字典.集合都可以被for循环,说明他们都是可迭代的 可迭代协议 : 就是内部实现了__iter__方法 可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__ite ...

  10. 目标检测方法——R-FCN

    R-FCN论文阅读(R-FCN: Object Detection via Region-based Fully Convolutional Networks ) 目录 作者及相关链接 方法概括 方法 ...