一种nb算法,可以求出数列的递推式。

具体过程是这样的。

我们先假设它有一个递推式,然后按位去算他的值。

for(int j=;j<now.size();++j)(delta[i]+=1ll*now[j]*f[i-j-]%mod)%=mod;

这是我们算出了f[i]应当是多少,但是f[i]有可能不是我们算出的值,所以我们记录一个delta,为我们算出的值减去f[i]的结果。

然后查看一下之前有没有出过锅。

如果出过,那么就补一个0,然后塞过去。。

if(!cnt){now.resize(i);cnt++;continue;}

cnt记录出锅次数,now记录当前递推式。

然后我们需要构造一个递推式把这一位的delta补上。

然后我们设inv为这一次的dalta除以上一次的delta。

然后我们的递推式就是在last和now之间补0,然后加一个inv,后面把所有的pre*(-inv)加进去,这样最后n这个位置会出现-delta就满足我们的要求了。

最后我们把构造递推式和当前递推式加起来。

再贪心选一个左端点最靠右的出锅递推式作为last。

正确性???

代码

#include<iostream>
#include<cstdio>
#include<vector>
#define N 100009
using namespace std;
typedef long long ll;
const ll mod=;
ll n,f[N],delta[N],fail[N],cnt,last;
vector<ll>cur,now,pre;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline ll power(ll x,ll y){
ll ans=;
while(y){
if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;
}
return ans;
} int main(){
n=rd();
for(int i=;i<=n;++i)f[i]=rd();
for(int i=;i<=n;++i){
delta[i]=mod-f[i];
for(int j=;j<now.size();++j)(delta[i]+=1ll*now[j]*f[i-j-]%mod)%=mod;
if(!delta[i])continue;
fail[cnt]=i;
if(!cnt){now.resize(i);cnt++;continue;}
ll inv=((mod-1ll*delta[i]*power(delta[fail[last]],mod-)%mod)%mod+mod)%mod;
cur.clear();cur.resize(i-fail[last]-);cur.push_back(mod-inv);
for(int j=;j<pre.size();++j)cur.push_back(1ll*pre[j]*inv%mod);
if(now.size()>cur.size())cur.resize(now.size());
for(int j=;j<now.size();++j)(cur[j]+=now[j])%=mod;
if(i-now.size()>=fail[last]-pre.size())pre=now,last=cnt; //fail[last]!!!
cnt++;now=cur;
}
for(int i=;i<now.size();++i)cout<<now[i]<<",";cout<<now.size();
return ;
}

应用

[NOI2007]生成树计数

正解貌似是插头dp+快速幂。

然后我们发现k非常小。。。。

那么就可以对于每一个k打一个表,然后再扔到BM里跑一下,发现转移式子最大只有45。

于是就直接上矩乘。

代码

打表

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 402
using namespace std;
typedef long long ll;
ll a[N][N],n;
const int mod=;
inline ll power(ll x,ll y){
ll ans=;
while(y){
if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;
}
return ans;
}
inline ll ni(ll x){return power(x,mod-);}
inline ll matr(int n){
for(int i=;i<=n;++i){
for(int j=i+;j<=n;++j){
ll x=1ll*a[j][i]*ni(a[i][i])%mod;
for(int k=i;k<=n;++k)a[j][k]=(a[j][k]-x*a[i][k]%mod+mod)%mod;
}
}
ll ans=;
for(int i=;i<=n;++i)ans=ans*a[i][i]%mod;
return ans;
}
int main(){
freopen("out","w",stdout);
int kk=;
for(int n=;n<=;++n){
memset(a,,sizeof(a));
for(int i=;i<=n;++i){
for(int k=i-;k>=&&k>=i-kk;--k)a[i][i]++,a[i][k]--;
for(int k=i+;k<=n&&k<=i+kk;++k)a[i][i]++,a[i][k]--;
}
printf("%lld,",matr(n-));
}
return ;
}

矩阵乘法

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=;
ll top,n;
int s1[]={,};
int s2[]={,,,};
int s3[]={,,,,,,,};
int s4[]={,,,,,,,,,,,,,,,,,};
int s5[]={,,,,,,,,,,,,,
,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,};
int a1[]={,};
int a2[]={,,,};
int a3[]={,,,,,,,};
int a4[]={,,,,,,,,,,,,,,,,,};
int a5[]={,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,
,,,,,,,,,,,};
inline ll power(ll x,ll y){
ll ans=;
while(y){if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;}
return ans;
}
struct matrix{
ll a[][];
matrix(){memset(a,,sizeof(a));}
matrix operator *(const matrix &b)const{
matrix c;
for(int i=;i<=top;++i)
for(int j=;j<=top;++j){
for(int k=;k<=top;++k)
(c.a[i][j]+=a[i][k]*b.a[k][j]%mod)%=mod;
}
return c;
}
}ans,Z;
inline void work1(){
puts("");
}
inline void work2(){
if(n<=){printf("%d\n",a2[n]);return;}
for(int i=;i<=;++i){
ans.a[][i]=a2[i];
Z.a[i][]=s2[-i+];
if(i!=)Z.a[i][i-]=;
}
n-=;top=;
while(n){
if(n&)ans=ans*Z;
Z=Z*Z;
n>>=;
}
printf("%lld",ans.a[][]);
}
inline void work3(){
if(n<=){printf("%d\n",a3[n]);return;}
for(int i=;i<=;++i){
ans.a[][i]=a3[i];
Z.a[i][]=s3[-i+];
if(i!=)Z.a[i][i-]=;
}
n-=;top=;
while(n){
if(n&)ans=ans*Z;
Z=Z*Z;
n>>=;
}
printf("%lld",ans.a[][]);
}
inline void work4(){
if(n<=){printf("%d\n",a4[n]);return;}
for(int i=;i<=;++i){
ans.a[][i]=a4[i];
Z.a[i][]=s4[-i+];
if(i!=)Z.a[i][i-]=;
}
n-=;top=;
while(n){
if(n&)ans=ans*Z;
Z=Z*Z;
n>>=;
}
printf("%lld",ans.a[][]);
}
inline void work5(){
if(n<=){printf("%d\n",a5[n]);return;}
for(int i=;i<=;++i){
ans.a[][i]=a5[i];
Z.a[i][]=s5[-i+];
if(i!=)Z.a[i][i-]=;
}
n-=;top=;
while(n){
if(n&)ans=ans*Z;
Z=Z*Z;
n>>=;
}
printf("%lld",ans.a[][]);
}
int main(){
int k;
cin>>k>>n;
if(k==)work1();
else if(k==)work2();
else if(k==)work3();
else if(k==)work4();
else if(k==)work5();
return ;
}

BM算法学习笔记的更多相关文章

  1. Berlekamp_Massey 算法 (BM算法) 学习笔记

    原文链接www.cnblogs.com/zhouzhendong/p/Berlekamp-Massey.html 前言 BM算法用于求解常系数线性递推式. 它可以在 $O(n^2)$ 的时间复杂度内解 ...

  2. C / C++算法学习笔记(8)-SHELL排序

    原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...

  3. Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...

  4. Johnson算法学习笔记

    \(Johnson\)算法学习笔记. 在最短路的学习中,我们曾学习了三种最短路的算法,\(Bellman-Ford\)算法及其队列优化\(SPFA\)算法,\(Dijkstra\)算法.这些算法可以快 ...

  5. 某科学的PID算法学习笔记

    最近,在某社团的要求下,自学了PID算法.学完后,深切地感受到PID算法之强大.PID算法应用广泛,比如加热器.平衡车.无人机等等,是自动控制理论中比较容易理解但十分重要的算法. 下面是博主学习过程中 ...

  6. Johnson 全源最短路径算法学习笔记

    Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...

  7. 算法学习笔记——sort 和 qsort 提供的快速排序

    这里存放的是笔者在学习算法和数据结构时相关的学习笔记,记录了笔者通过网络和书籍资料中学习到的知识点和技巧,在供自己学习和反思的同时为有需要的人提供一定的思路和帮助. 从排序开始 基本的排序算法包括冒泡 ...

  8. R语言实现关联规则与推荐算法(学习笔记)

    R语言实现关联规则 笔者前言:以前在网上遇到很多很好的关联规则的案例,最近看到一个更好的,于是便学习一下,写个学习笔记. 1 1 0 0 2 1 1 0 0 3 1 1 0 1 4 0 0 0 0 5 ...

  9. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

随机推荐

  1. 微信小程序(二)登录授权实现

    相对于上一节,这一节主要是动态获取数据,主要是对登陆信息的接收,以及页面获取授权按钮的相对相应(未授权时,显示,授权后不显示) 关键在于状态值的判断,以及对页面的不同响应(m-->v) wxml ...

  2. C++ 死循环在语言层面的检测

    英文概念 Infinite loop without side-effects 这个目前只有CLang实现了这个C++特色 #include <iostream> int 费马定理() { ...

  3. JavaScript中的闭包和作用域链

    这部分几乎是JavaScript中最难的部分,也是面试官最爱问的地方. 下面的内容是我以前写的<JavaScript学习手册>中被客户删除的部分,理由听起来有点诡异:太难.

  4. 基于Angular和Spring WebFlux做个小Demo

    前言 随着Spring Boot2.0正式发布,Spring WebFlux正式来到了Spring Boot大家族里面.由于Spring WebFlux可以通过更少的线程去实现更高的并发和使用更少的硬 ...

  5. redis常用命令大全

    1.基于内存的key-value数据库 2.基于c语言编写的,可以支持多种语言的api //set每秒11万次,取get 81000次 3.支持数据持久化 4.value可以是string,hash, ...

  6. MySQL之库相关操作

    一 系统数据库 information_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息.列信息.权限信息.字符信息等performance_schema: MyS ...

  7. Linux-基础学习(五)-mariadb主从复制以及redis学习

    开始今日份整理 1.mariadb的主从复制 主从复制大致图示: 1.1 mysql基本命令复习 linux下的操作 .启动mysql systemctl start mariadb .linux客户 ...

  8. python3 二分法查找

    '''二分法查找有序列表掐头去尾取中间查找列表中xx在不在列表中,在,则返回索引值'''# lst = [1, 4, 6, 8, 9, 21, 23, 26, 35, 48, 49, 54, 67, ...

  9. web服务器、tomcat、servlet是什么?它们之间的关系又是什么?

    今天偶然看到常见web服务器的介绍有Apache HTTP server.Nginx.Microsoft IIS.GWS,心中不禁产生了疑问,这些都是什么呢?一直认为tomcat就是web服务器,以下 ...

  10. Docker启动的问题解决笔记

    一.错误信息1:解决VM 与 Device/Credential Guard 不兼容  错误原因: 1.出现此问题的原因是Device Guard或Credential Guard与Workstati ...