【瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)
【背诵瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)
看CSP看到一题“线性递推式”,不会做,去问了问zsy怎么做,他并不想理我并丢给我以下方法:
\]
下文会根据CH定理证明的思路证明,没有形式上使用特征系统,因为我也不会...
复读鸽子讲的话
一句话就是求:
\]
但这个算法卡常,zsy说1e5估计要跑10s
先求前\(m\)项
前\(m\)项的话,递推关系就变成这样:
\]
钦定\(c_0=0\),则写成生成函数\(F(x)=\sum f_{i+1}x^i,C(x)=\sum c_ix^i\),则
\]
为什么有个\(f_1\)?因为你会发现按照定义\(F(x)\)少了常数项(\(c_0=0\) )
解出来
\]
就是:
\]
所以直接就求出来了前\(m\)项
增广矩阵的特征多项式
我们规范一下平常用的矩阵快速幂的格式:
设\(m\)阶增广矩阵\(A\),我们所谓的增广是这样的:
对于行向量\(e=(f_1,f_2,\dots,f_{m-1},f_{m})\),则:
\]
我们就是要求\(f_{1+n}\)。归纳地理解上面这个式子,这是我们对\(A\)的定义,根据递推关系很容易构造出一个满足条件的\(A\)
\\
a_{i,i+1}=1,i\in[1,m-1]
\]
大概是这样的
0&0&0&0&\dots&a_1
\\
1&0&0&0&\dots&a_2
\\
0&1&0&0&\dots&a_3
\\
0&0&1&0&\dots&a_4
\\
\vdots&\vdots&\vdots&\vdots&\ddots&\vdots
\\
0&0&0&0&1&a_m
\end{pmatrix}
\]
我们新建一个生成函数\(F(x)\)(和前面那个没有关系,上面那个是一个“局部变量”hhh)
\]
这个多项式叫做A的特征多项式,我们带入\(A\)进去有:
\]
如何证明?先移项再左乘一个行向量\(e\),定义在上面
\]
根据\(e\)和\(A\)之间的定义,直接变成
\]
考虑一下第\(j\)维的值,两边分别为
\]
显然成立。故对于每一维相等,故左右两个向量相等。
故原命题成立。
好现在我们就证明了
\]
这其实是我们的"初始条件"
假设会求\(A^n\)了,我们怎么得到\(f_n\)?
请仔细阅读标题
我们之前得到了:
\]
考虑我们实质上干了什么?实际上我们就把下标换成了指数。也就是说,我们可以把\(A\)的任意次方化为若干\(A^i,i\le m\)的和表示出来。 这意味着我们可能可以利用指数有结合律的优美性质。
形式化的,我们就得到了这样一个\(b[]\)数组,使得:
\]
然而,\(A\)是一个\(m\times m\)的方阵,\(m\le 1e5\)。我们是不可能对于\(A\)在程序中进行任何矩阵\(O(n^2),O(n^3)\)的操作的,否则超时(理解我的意思就好)。
但是我们只是要求\(f_n\),所以两边直接同右乘以\(e\)就好了。
就是
\]
然后根据定义,我们就直接得到了这个:
\]
然而我们只需要第一个\(f_{1+n}\)
所以把第一维单独拿出来:
\]
矩阵已经消失了,剩下的只有一个\(O(m)\)的式子。
现在问题就变成了要求\(b[]\)数组,然后就直接\(O(m)\)算\(f_{1+n}\)了
那么到底如何球\(b[]\)数组呢?
关键的系数\(b_i\)
现在的问题变成了如何得到\(b_i\)数组
递归地思考,我们考虑任何时刻用他的系数\(b[]\)数组,不及\(m\)位的补\(0\)。例如:\(A^1->b[]=\underbrace {\{0,0,0,\underbrace {1}_{m-1\_th},\dots\}}_{m}\)来表示我们当前的状态。
两个\(A^1\)相乘就构成\(A^2\),我们就可以倍增求我们要的\(A^n\) 。
然而每次相乘会出现\(2m-2\)次方,不符合要求啊,怎么办?但是我们有个关系式
\]
代入我们之前得到的\(2m-2\)次方多项式里,所有次数大于\(m\)的项都会被化为小于\(m\)的形式,现在就是要快速带入这个关系式
最神奇的事情发生了!!
带入
\]
就相当于认为
\]
也就是对\(x^m-\sum_{i=1}^mc_ix^{m-i}\)多项式取膜!!1
很拍脑袋的解释是吧,其实是有科学说明的:
考虑取模那个定义的式子,可以发现是F=MOD*Q+R,R是余数,由于我们带入前式也是带入MOD=0进去,现在就很显然啦
于是就一边从\(A^1\)对应的那个系数倍增,一边倍增一边对\(x^m-\sum_{i=1}^mc_ix^{m-i}\)多项式取膜就好了!!1。
多项式取膜一个log,加上倍增,总复杂度\(O(m\log m\log n)\),常数真 的 好 大 啊
orz-orz--orz--orz--orz--orz--orz--orz--orz--orz--orz--orz-分鸽线-orz--orz--orz--orz--orz--orz--orz--orz--orz--orz--orz--orz--orz--orz--orz--orz-
代码
在路上了在路上了
觚不觚,觚哉觚哉!
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<assert.h>
#define getchar() (__c==__ed?(__ed=__buf+fread(__c=__buf,1,1<<18,stdin),*__c++):*__c++)
using namespace std; typedef long long ll; char __buf[1<<18],*__c=__buf,*__ed=__buf;
inline int qr(){
int ret=0,f=0,c=getchar();
while(!isdigit(c))f|=c==45,c=getchar();
while(isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int mod=998244353;
const int maxn=1<<16;
inline int MOD(const int&x){return x>=mod?x-mod:x;}
inline int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
inline int ksm(const int&ba,const int&p){
int ret=1;
for(int t=p,b=ba;t;t>>=1,b=MOD(b,b))
if(t&1) ret=MOD(ret,b);
return ret;
}
namespace poly{
const int g=3,gi=(mod+1)/3;
void NTT(int*a,const int&len,const int&tag){
static int r[maxn];
for(int t=0;t<len;++t)
if((r[t]=r[t>>1]>>1|(t&1?len>>1:0))<t)
swap(a[t],a[r[t]]);
for(int t=1,wn,s=tag==1?g:gi;t<len;t<<=1){
wn=ksm(s,(mod-1)/(t<<1));
for(int i=0;i<len;i+=t<<1)
for(int j=0,w=1,p;j<t;++j,w=MOD(w,wn))
p=MOD(w,a[i+j+t]),a[i+j+t]=MOD(a[i+j]-p+mod),a[i+j]=MOD(a[i+j]+p);
}
if(tag!=1)
for(int t=0,i=mod-(mod-1)/len;t<len;++t)
a[t]=MOD(a[t],i);
}
void INV(int*a,int*b,const int&len){
if(len==1) return b[0]=ksm(a[0],mod-2),void();
INV(a,b,len>>1);
static int A[maxn],B[maxn];
memset(A,0,len<<3); memset(B,0,len<<3);
memcpy(A,a,len<<2); memcpy(B,b,len<<2);
NTT(A,len<<1,1); NTT(B,len<<1,1);
for(int t=0;t<len<<1;++t) A[t]=MOD(A[t],MOD(B[t],B[t]));
NTT(A,len<<1,0);
for(int t=0;t<len;++t) b[t]=MOD(MOD(B[t]+B[t])-A[t]+mod);
}
int sav[maxn],invsav[maxn],n,m;//2^
void MOD(int*a){
static int A[maxn],B[maxn];
int len=n;
memset(A,0,len<<3); memset(B,0,len<<3);
memcpy(A,a,len<<2); reverse(A,A+len);
NTT(A,len<<1,1);
for(int t=0;t<len<<1;++t) A[t]=::MOD(A[t],invsav[t]);
NTT(A,len<<1,0);
reverse(A,A+len); memset(A+len,0,len<<2);
NTT(A,len<<1,1);
for(int t=0;t<len<<1;++t) A[t]=::MOD(A[t],sav[t]);
NTT(A,len<<1,0);
for(int t=0;t<=m;++t) a[t]=::MOD(a[t]-A[t]+mod);
//F*G
}
void KSM(int*a,int*Mod,int p){
static int ret[maxn],base[maxn];
memset(ret,0,sizeof ret); memset(base,0,sizeof base);
ret[0]=1;
for(int t=0;t<n;++t) base[t]=a[t];
while(p){
p>>=1;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
return 0;
}
【瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)的更多相关文章
- 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)
这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...
- 常系数齐次线性递推 & 拉格朗日插值
常系数齐次线性递推 具体记在笔记本上了,以后可能补照片,这里稍微写一下,主要贴代码. 概述 形式: \[ h_n = a_1 h_{n-1}+a_2h_{n-2}+...+a_kh_{n-k} \] ...
- 【Luogu4723】线性递推(常系数齐次线性递推)
[Luogu4723]线性递推(常系数齐次线性递推) 题面 洛谷 题解 板子题QwQ,注意多项式除法那里每个多项式的系数,调了一天. #include<iostream> #include ...
- 【BZOJ4161】Shlw loves matrixI (常系数齐次线性递推)
[BZOJ4161]Shlw loves matrixI (常系数齐次线性递推) 题面 BZOJ 题解 \(k\)很小,可以直接暴力多项式乘法和取模. 然后就是常系数齐次线性递推那套理论了,戳这里 # ...
- BZOJ4161 常系数齐次线性递推
问了数竞的毛毛搞了一番也没太明白,好在代码蛮好写先记下吧. #include<bits/stdc++.h> using namespace std; ,mod=1e9+; int n,k, ...
- 【BZOJ4944】[NOI2017]泳池(线性常系数齐次递推,动态规划)
[BZOJ4944][NOI2017]泳池(线性常系数齐次递推,动态规划) 首先恰好为\(k\)很不好算,变为至少或者至多计算然后考虑容斥. 如果是至少的话,我们依然很难处理最大面积这个东西.所以考虑 ...
- Re.常系数齐次递推
前言 嗯 我之前的不知道多少天看这个的时候到底在干什么呢 为什么那么.. 可能大佬们太强的缘故 最后仔细想想思路那么的emmm 不说了 要落泪了 唔唔唔 前置 多项式求逆 多项式除法/取模 常 ...
- 线性齐次递推式快速求第n项 学习笔记
定义 若数列 \(\{a_i\}\) 满足 \(a_n=\sum_{i=1}^kf_i \times a_{n-i}\) ,则该数列为 k 阶齐次线性递推数列 可以利用多项式的知识做到 \(O(k\l ...
- 2019牛客暑期多校训练营(第五场)- B generator 1 (齐次线性递推+矩阵快速幂)
题目链接:https://ac.nowcoder.com/acm/contest/885/B 题意:已知齐次线性式xn=a*xn-1+b*xn-2,已知a,b,x0,x1,求xn,n很大,n<= ...
随机推荐
- Gym-101623H_High Score
题意:t组数据,每组数据有abcd四个数,其中d可以加到abc任意一个数上(d可以拆分),求公式a^2 + b^2 + c^2 + 7 * min(a,b,c)的最大值. 题解:首先明确一点,平方的增 ...
- Java练习 SDUT-1211_英文金曲大赛
英文金曲大赛 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 我们在"渊子数"的题目中已经了解了渊子 ...
- 18-2 djanjo中间件和orm多对多操作,以及ajax
一 中间件 0 怎样使用中间件 在setting配置文件里面注册你的中间件,如下: 'mymiddleware.MD1', 前面是文件名,后面是类名 然后在你的mymiddleware文件里导入: ...
- Facebook F8|闲鱼高级技术专家参会分享
笔者代表闲鱼参加了Facebook在4月30日举行的为期二天的F8大会,地点加州.将会议概括和一些收获分享给大家.对国内开发者而言,Facebook的产品设计.社区.VR/AR等有一些借鉴意义:对海外 ...
- vue element 给指数的div加loading
const loading = this.$loading({ lock: true, text: 'Loading', spinner: 'el-icon-lo ...
- OpenStack组件系列☞Keystone
Keystone(OpenStack Identity Service)是 OpenStack 框架中负责管理身份验证.服务规则和服务令牌功能的模块.用户访问资源需要验证用户的身份与权限,服务执行操作 ...
- react项目安装及运行
博客地址 :https://www.cnblogs.com/sandraryan/ 安装node ,有就跳过. node.js官网:https://nodejs.org/en/ 终端用node -v ...
- Google Colab——用谷歌免费GPU跑你的深度学习代码
Google Colab简介 Google Colaboratory是谷歌开放的一款研究工具,主要用于机器学习的开发和研究.这款工具现在可以免费使用,但是不是永久免费暂时还不确定.Google Col ...
- window10+python3.7安装tensorflow--gpu tensorflow 安装
能安装GPU的前提是:1.显卡支持CUDA (1)右击我的电脑–属性 (2)打开设备管理器 (3)显示适配器 我的电脑是支持CUDA的 2.pip 版本 >= 8.1查看pip版本 :pip ...
- 评分模型的检验方法和标准通常有:K-S指标、交换曲线、AR值、Gini数等。例如,K-S指标是用来衡量验证结果是否优于期望值,具体标准为:如果K-S大于40%,模型具有较好的预测功能,发展的模型具有成功的应用价值。K-S值越大,表示评分模型能够将“好客户”、“坏客户”区分开来的程度越大。
评分模型的检验方法和标准通常有:K-S指标.交换曲线.AR值.Gini数等.例如,K-S指标是用来衡量验证结果是否优于期望值,具体标准为:如果K-S大于40%,模型具有较好的预测功能,发展的模型具有成 ...