BM算法求求线性递推式

 

P5487 线性递推+BM算法

  待AC。

 

Poor God Water

  // 题目来源:[ACM-ICPC 2018 焦作赛区网络预赛](https://nanti.jisuanke.com/acm?kw=ACM-ICPC 2018 焦作赛区网络预赛)

题意

  God Water喜欢吃Meat, Fish 和 Chocolate,每个小时他会吃一种食物,但有些吃的顺序是危险/不高兴的。求在N小时内他的饮食方案有多少种不同组合。在连续三小时内这些组合是不可行的:

unhappy :

MMM FFF CCC

dangerous :

MCF FCM CMC CFC

 

思路1

  设第 N 小时能吃的饮食方案数为 A[N],根据连续三小时的可能组合,我们可以发现 A[N] 可以由 A[N-1] 和 A[N-2] 递推得到。由于相邻两小时的组合不是独立的,不能利用乘法计数原理。

  用向量 a[N] = (MM, FM, CM, MF, FF, CF, MC, FC, CC) 记录 N 小时的最后两小时所吃的食物状态总的方案数,那么只需要找到矩阵 A,使得 a[N-1] · A = a[N],那么就能用矩阵快速幂解决。

  构造的矩阵如下:

\[A = \begin{bmatrix}
0&1&1&0&0&0&0&0&0\\
0&0&0&1&1&1&0&0&0\\
0&0&0&0&0&0&1&0&1\\
1&1&1&0&0&0&0&0&0\\
0&0&0&1&0&1&0&0&0\\
0&0&0&0&0&0&0&1&1\\
1&1&0&0&0&0&0&0&0\\
0&0&0&1&1&0&0&0&0\\
0&0&0&0&0&0&1&1&0
\end{bmatrix}
\]

 

思路2

  使用杜教的BM算法模板,扔进8~10项,调用linear_seq::gao函数直接求 N 项结果。 时间复杂度与矩阵快速幂等同。

 

AC代码1

#include<iostream>
#include<cstdio>
using namespace std;
const int mod = 1e9+7; typedef long long ll;
struct Mat {
ll m[9][9];
ll tot;
Mat operator*(const Mat& a)const {
Mat res = {0};
for(int i=0;i<9;i++) {
for(int j=0;j<9;j++) {
for(int k=0;k<9;k++) {
res.m[i][j] += m[i][k] * a.m[k][j] % mod;
res.m[i][j] %= mod;
}
// res.tot =(res.tot + res.m[i][j]) % mod;
}
}
return res;
}
ll getSum() const {
// return tot;
ll res = 0;
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
res = (res + m[i][j]) % mod;
return res;
}
void print() const {
for(int i=0;i<9;i++) {
for(int j=0;j<9;j++) {
printf("%lld ", m[i][j]);
}
printf("\n");
}
}
}; Mat getI() {
Mat I = {0};
for(int i=0;i<9;i++)
I.m[i][i] = 1;
return I;
}
const Mat I = getI(); Mat getA0() {
Mat res = {0};
for(int k=0;k<3;k++)
for(int i=0;i<3;i++) {
for(int j=3*i;j<3*i+3;j++)
res.m[k*3+i][j] = 1;
}
res.m[0][0] = 0;
res.m[2][7] = 0;
res.m[4][4] = 0;
res.m[5][6] = 0;
res.m[6][2] = 0;
res.m[7][5] = 0;
res.m[8][8] = 0;
res.tot = 20;
return res;
}
const Mat A0 = getA0(); Mat pow_mod(Mat a, ll n) {
Mat res = I;
while(n) {
if(n&1) res = res*a;
a = a*a;
n >>= 1;
}
return res;
} ll solve(ll n) {
if(n==1) return 3;
else if(n==2) return 9; return pow_mod(A0, n-2).getSum();
} int main() {
int T; cin>>T;
while(T--) {
ll n;
scanf("%lld", &n);
printf("%lld\n", solve(n));
}
return 0;
} /*
MFC
3*3*3 = 27 unhappy:
MMM
FFF
CCC dangerous:
MCF
FCM CMC
CFC M F C
MM 0 1 1
MF 1 1 1
MC 1 0 1 FM 1 1 1
FF 1 0 1
FC 0 1 1 CM 1 1 0
CF 1 1 0
CC 1 1 0
*/

 

AC代码2

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std; #define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size()) typedef long long ll;
typedef vector<ll> VLL;
const ll mod = 1000000007; ll powmod(ll a, ll b) {
ll res=1;a%=mod;
for(;b;b>>=1) {
if(b&1) res=res*a%mod;
a=a*a%mod;
}
return res;
} ll n;
namespace linear_seq {
const int N = 100010;
ll res[N], base[N], _c[N], _md[N]; VLL Md;
void mul(ll a[], ll b[], int k) {
for(int i=0;i<k+k;i++)
_c[i] = 0;
for(int i=0;i<k;i++)
if(a[i])
for(int j=0;j<k;j++)
_c[i+j] = (_c[i+j] + a[i]*b[j]%mod) % mod; for(int i=k+k-1;i>=k;i--)
if(_c[i])
rep(j,0,SZ(Md))
_c[i-k+Md[j]] = (_c[i-k+Md[j]] - _c[i] * _md[Md[j]]%mod) % mod; for(int i=0;i<k;i++)
a[i] = _c[i];
} ll solve(ll n, VLL a, VLL b) {
ll ans = 0, pnt = 0;
int k = SZ(a);
for(int i=0;i<k;i++)
_md[k-1-i]=-a[i];
_md[k]=1; Md.clear();
for(int i=0;i<k;i++)
if(_md[i]!=0) Md.push_back(i);
for(int i=0;i<k;i++)
res[i]=base[i]=0;
res[0]=1; while((1ll<<pnt)<=n) pnt++;
for(int p=pnt;p>=0;p--) {
mul(res, res, k);
if((n>>p)&1) {
for(int i=k-1;i>=0;i--)
res[i+1]=res[i];res[0]=0;
rep(j,0,SZ(Md))
res[Md[j]]=(res[Md[j]] - res[k]*_md[Md[j]]%mod) % mod;
}
} for(int i=0;i<k;i++)
ans = (ans + res[i]*b[i]%mod) % mod;
if(ans<0) ans += mod;
return ans;
} VLL BM(VLL s) {
VLL C(1,1), B(1,1);
int L=0,m=1,b=1;
rep(n,0,SZ(s)) {
ll d=0;
rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i]%mod) % mod;
if(d==0) ++m;
else if(2*L<=n) {
VLL T=C;
ll c=mod-d*powmod(b,mod-2)%mod;
while(SZ(C)<SZ(B)+m) C.pb(0);
rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i]%mod) % mod;
L=n+1-L; B=T; b=d; m=1;
} else {
ll c = mod- d*powmod(b, mod-2)%mod;
while(SZ(C)<SZ(B)+m) C.pb(0);
rep(i,0,SZ(B))
C[i+m]=(C[i+m]+c*B[i]%mod) % mod;
++m;
}
}
return C;
} ll gao(VLL a, ll n) {
VLL c = BM(a);
c.erase(c.begin());
rep(i,0,SZ(c))
c[i] = (mod-c[i])%mod;
return solve(n, c, VLL(a.begin(), a.begin()+SZ(c)));
}
}; int main() {
/*push_back 进去前 8~10 项左右、最后调用 gao 得第 n 项*/
vector<int>v;
v.pb(3);
v.pb(9);
v.pb(20);
v.pb(46);
v.pb(106);
v.pb(244);
v.pb(560);
v.pb(1286);
v.pb(2956);
v.pb(6794);
int T;
scanf("%d", &T);
while(T--){
scanf("%lld", &n);
printf("%lld\n", linear_seq::gao(v,n-1));
}
}

 

Berlekamp Massey算法求线性递推式的更多相关文章

  1. bzoj4161 (k^2logn求线性递推式)

    分析: 我们可以写把转移矩阵A写出来,然后求一下它的特征多项式,经过手动计算应该是这样的p(x)=$x^k-\sum\limits_{i=1}^ka_i*x^{k-i}$ 根据Cayley-Hamil ...

  2. 矩阵乘法&矩阵快速幂&矩阵快速幂解决线性递推式

    矩阵乘法,顾名思义矩阵与矩阵相乘, 两矩阵可相乘的前提:第一个矩阵的行与第二个矩阵的列相等 相乘原则: a b     *     A B   =   a*A+b*C  a*c+b*D c d     ...

  3. 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)

    这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...

  4. BM求线性递推模板(杜教版)

    BM求线性递推模板(杜教版) BM求线性递推是最近了解到的一个黑科技 如果一个数列.其能够通过线性递推而来 例如使用矩阵快速幂优化的 DP 大概都可以丢进去 则使用 BM 即可得到任意 N 项的数列元 ...

  5. 2018 焦作网络赛 L Poor God Water ( AC自动机构造矩阵、BM求线性递推、手动构造矩阵、矩阵快速幂 )

    题目链接 题意 : 实际上可以转化一下题意 要求求出用三个不同元素的字符集例如 { 'A' .'B' .'C' } 构造出长度为 n 且不包含 AAA.BBB CCC.ACB BCA.CAC CBC ...

  6. 线性齐次递推式快速求第n项 学习笔记

    定义 若数列 \(\{a_i\}\) 满足 \(a_n=\sum_{i=1}^kf_i \times a_{n-i}\) ,则该数列为 k 阶齐次线性递推数列 可以利用多项式的知识做到 \(O(k\l ...

  7. LG5487 【模板】线性递推+BM算法

    [模板]线性递推+BM算法 给出一个数列 \(P\) 从 \(0\) 开始的前 \(n\) 项,求序列 \(P\) 在\(\bmod~998244353\) 下的最短线性递推式,并在 \(\bmod~ ...

  8. P1067Warcraft III 守望者的烦恼(十大矩阵问题之七求递推式)

    https://vijos.org/p/1067 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她 ...

  9. 【瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)

    [背诵瞎讲] Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18) 看CSP看到一题"线性递推式",不会做,去问了问zsy怎么做,他并 ...

随机推荐

  1. 移动端布局 + iscroll.js

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...

  2. leetcode-两个数组的交集

    C++解题方法: class Solution { public: vector<int> intersection(vector<int>& nums1, vecto ...

  3. NX二次开发-UFUN按类型遍历名字获取Tag函数UF_OBJ_cycle_by_name_and_type

    NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_obj.h> #include <u ...

  4. ionic-CSS:ionic 卡片

    ylbtech-ionic-CSS:ionic 卡片 1.返回顶部 1. ionic 卡片 近年来卡片(card)的应用越来越流行,卡片提供了一个更好组织信息展示的工具. 针对移动端的应用,卡片会根据 ...

  5. spring boot读取自定义配置文件时乱码解决办法

    @PropertySource(value = "classpath:book.yml", ignoreResourceNotFound = true,encoding = &qu ...

  6. class12_pack_grid_place 放置位置

    其中的部分运行效果图(程序见序号1): #!/usr/bin/env python# -*- coding:utf-8 -*-# ----------------------------------- ...

  7. ncurse 笔记

    初始化与结束 为了使用 NCURSES 库,你应该 #include <curses.h>,在编译时,应该加上 -lncurses. stdscr 一般地,第一个函数调用必须是 inits ...

  8. A1075 PAT Judge (25 分)

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...

  9. 解决jqGrid中,当前页一直显示为0的问题

    项目中,经常会见到使用 jqGrid 进行一些数据的列表展示,而且使用起来也比较方便.但是有时会遇到一些奇怪的问题,比如前几天我就遇到了在使用 jqGrid 时,当前页一直显示为 0 的问题.下图就是 ...

  10. 《DSP using MATLAB》Problem 9.2

    前几天看了看博客,从16年底到现在,3年了,终于看书到第9章了.都怪自己愚钝不堪,唯有吃苦努力,一点一点一页一页慢慢啃了. 代码: %% ------------------------------- ...