BM线性递推

玄学玩意

struct LinearRecurrence
{
using int64 = long long;
using vec = std::vector<int64>; static void extand(vec& a, size_t d, int64 value = )
{
if (d <= a.size()) return;
a.resize(d, value);
}
static vec BerlekampMassey(const vec& s, int64 mod)
{
std::function<int64(int64)> inverse = [&](int64 a) {
return a == ? : (int64)(mod - mod / a) * inverse(mod % a) % mod;
};
vec A = {}, B = {};
int64 b = s[];
for (size_t i = , m = ; i < s.size(); ++i, m++)
{
int64 d = ;
for (size_t j = ; j < A.size(); ++j)
{
d += A[j] * s[i - j] % mod;
}
if (!(d %= mod)) continue;
if ( * (A.size() - ) <= i)
{
auto temp = A;
extand(A, B.size() + m);
int64 coef = d * inverse(b) % mod;
for (size_t j = ; j < B.size(); ++j)
{
A[j + m] -= coef * B[j] % mod;
if (A[j + m] < ) A[j + m] += mod;
}
B = temp, b = d, m = ;
}
else
{
extand(A, B.size() + m);
int64 coef = d * inverse(b) % mod;
for (size_t j = ; j < B.size(); ++j)
{
A[j + m] -= coef * B[j] % mod;
if (A[j + m] < ) A[j + m] += mod;
}
}
}
return A;
}
static void exgcd(int64 a, int64 b, int64& g, int64& x, int64& y)
{
if (!b)
x = , y = , g = a;
else
{
exgcd(b, a % b, g, y, x);
y -= x * (a / b);
}
}
static int64 crt(const vec& c, const vec& m)
{
int n = c.size();
int64 M = , ans = ;
for (int i = ; i < n; ++i) M *= m[i];
for (int i = ; i < n; ++i)
{
int64 x, y, g, tm = M / m[i];
exgcd(tm, m[i], g, x, y);
ans = (ans + tm * x * c[i] % M) % M;
}
return (ans + M) % M;
}
static vec ReedsSloane(const vec& s, int64 mod)
{
auto inverse = [](int64 a, int64 m) {
int64 d, x, y;
exgcd(a, m, d, x, y);
return d == ? (x % m + m) % m : -;
};
auto L = [](const vec& a, const vec& b) {
int da = (a.size() > || (a.size() == && a[])) ? a.size() - : -;
int db = (b.size() > || (b.size() == && b[])) ? b.size() - : -;
return std::max(da, db + );
};
auto prime_power = [&](const vec& s, int64 mod, int64 p, int64 e) {
// linear feedback shift register mod p^e, p is prime
std::vector<vec> a(e), b(e), an(e), bn(e), ao(e), bo(e);
vec t(e), u(e), r(e), to(e, ), uo(e), pw(e + );
;
pw[] = ;
for (int i = pw[] = ; i <= e; ++i) pw[i] = pw[i - ] * p;
for (int64 i = ; i < e; ++i)
{
a[i] = {pw[i]}, an[i] = {pw[i]};
b[i] = {}, bn[i] = {s[] * pw[i] % mod};
t[i] = s[] * pw[i] % mod;
if (t[i] == )
{
t[i] = , u[i] = e;
}
else
{
for (u[i] = ; t[i] % p == ; t[i] /= p, ++u[i])
;
}
}
for (size_t k = ; k < s.size(); ++k)
{
for (int g = ; g < e; ++g)
{
if (L(an[g], bn[g]) > L(a[g], b[g]))
{
ao[g] = a[e - - u[g]];
bo[g] = b[e - - u[g]];
to[g] = t[e - - u[g]];
uo[g] = u[e - - u[g]];
r[g] = k - ;
}
}
a = an, b = bn;
for (int o = ; o < e; ++o)
{
int64 d = ;
for (size_t i = ; i < a[o].size() && i <= k; ++i)
{
d = (d + a[o][i] * s[k - i]) % mod;
}
if (d == )
{
t[o] = , u[o] = e;
}
else
{
for (u[o] = , t[o] = d; t[o] % p == ; t[o] /= p, ++u[o])
;
int g = e - - u[o];
if (L(a[g], b[g]) == )
{
extand(bn[o], k + );
bn[o][k] = (bn[o][k] + d) % mod;
}
else
{
int64 coef = t[o] * inverse(to[g], mod) % mod * pw[u[o] - uo[g]] % mod;
int m = k - r[g];
extand(an[o], ao[g].size() + m);
extand(bn[o], bo[g].size() + m);
for (size_t i = ; i < ao[g].size(); ++i)
{
an[o][i + m] -= coef * ao[g][i] % mod;
if (an[o][i + m] < ) an[o][i + m] += mod;
}
while (an[o].size() && an[o].back() == ) an[o].pop_back();
for (size_t i = ; i < bo[g].size(); ++i)
{
bn[o][i + m] -= coef * bo[g][i] % mod;
if (bn[o][i + m] < ) bn[o][i + m] -= mod;
}
while (bn[o].size() && bn[o].back() == ) bn[o].pop_back();
}
}
}
}
return std::make_pair(an[], bn[]);
}; std::vector<std::tuple<int64, int64, int>> fac;
for (int64 i = ; i * i <= mod; ++i)
{
if (mod % i == )
{
int64 cnt = , pw = ;
while (mod % i == ) mod /= i, ++cnt, pw *= i;
fac.emplace_back(pw, i, cnt);
}
}
if (mod > ) fac.emplace_back(mod, mod, );
std::vector<vec> as;
size_t n = ;
for (auto&& x : fac)
{
int64 mod, p, e;
vec a, b;
std::tie(mod, p, e) = x;
auto ss = s;
for (auto&& x : ss) x %= mod;
std::tie(a, b) = prime_power(ss, mod, p, e);
as.emplace_back(a);
n = std::max(n, a.size());
}
vec a(n), c(as.size()), m(as.size());
for (size_t i = ; i < n; ++i)
{
for (size_t j = ; j < as.size(); ++j)
{
m[j] = std::get<>(fac[j]);
c[j] = i < as[j].size() ? as[j][i] : ;
}
a[i] = crt(c, m);
}
return a;
} LinearRecurrence(const vec& s, const vec& c, int64 mod) : init(s), trans(c), mod(mod), m(s.size()) {}
LinearRecurrence(const vec& s, int64 mod, bool is_prime = true) : mod(mod)
{
vec A;
if (is_prime)
A = BerlekampMassey(s, mod);
else
A = ReedsSloane(s, mod);
if (A.empty()) A = {};
m = A.size() - ;
trans.resize(m);
for (int i = ; i < m; ++i)
{
trans[i] = (mod - A[i + ]) % mod;
}
std::reverse(trans.begin(), trans.end());
init = {s.begin(), s.begin() + m};
}
int64 calc(int64 n)
{
if (mod == ) return ;
if (n < m) return init[n];
vec v(m), u(m << );
int msk = !!n;
for (int64 m = n; m > ; m >>= ) msk <<= ;
v[] = % mod;
for (int x = ; msk; msk >>= , x <<= )
{
std::fill_n(u.begin(), m * , );
x |= !!(n & msk);
if (x < m)
u[x] = % mod;
else
{ // can be optimized by fft/ntt
for (int i = ; i < m; ++i)
{
for (int j = , t = i + (x & ); j < m; ++j, ++t)
{
u[t] = (u[t] + v[i] * v[j]) % mod;
}
}
for (int i = m * - ; i >= m; --i)
{
for (int j = , t = i - m; j < m; ++j, ++t)
{
u[t] = (u[t] + trans[j] * u[i]) % mod;
}
}
}
v = {u.begin(), u.begin() + m};
}
int64 ret = ;
for (int i = ; i < m; ++i)
{
ret = (ret + v[i] * init[i]) % mod;
}
return ret;
} vec init, trans;
int64 mod;
int m;
};
接口: LinearRecurrence solver(f, mod, false);//f前若干项vector,mod模数,最后一个是否为质数
solver.calc(n);//计算第n项

The power of Fibonacci

#include<bits/stdc++.h>

struct LinearRecurrence
{
using int64 = long long;
using vec = std::vector<int64>; static void extand(vec& a, size_t d, int64 value = )
{
if (d <= a.size()) return;
a.resize(d, value);
}
static vec BerlekampMassey(const vec& s, int64 mod)
{
std::function<int64(int64)> inverse = [&](int64 a) {
return a == ? : (int64)(mod - mod / a) * inverse(mod % a) % mod;
};
vec A = {}, B = {};
int64 b = s[];
for (size_t i = , m = ; i < s.size(); ++i, m++)
{
int64 d = ;
for (size_t j = ; j < A.size(); ++j)
{
d += A[j] * s[i - j] % mod;
}
if (!(d %= mod)) continue;
if ( * (A.size() - ) <= i)
{
auto temp = A;
extand(A, B.size() + m);
int64 coef = d * inverse(b) % mod;
for (size_t j = ; j < B.size(); ++j)
{
A[j + m] -= coef * B[j] % mod;
if (A[j + m] < ) A[j + m] += mod;
}
B = temp, b = d, m = ;
}
else
{
extand(A, B.size() + m);
int64 coef = d * inverse(b) % mod;
for (size_t j = ; j < B.size(); ++j)
{
A[j + m] -= coef * B[j] % mod;
if (A[j + m] < ) A[j + m] += mod;
}
}
}
return A;
}
static void exgcd(int64 a, int64 b, int64& g, int64& x, int64& y)
{
if (!b)
x = , y = , g = a;
else
{
exgcd(b, a % b, g, y, x);
y -= x * (a / b);
}
}
static int64 crt(const vec& c, const vec& m)
{
int n = c.size();
int64 M = , ans = ;
for (int i = ; i < n; ++i) M *= m[i];
for (int i = ; i < n; ++i)
{
int64 x, y, g, tm = M / m[i];
exgcd(tm, m[i], g, x, y);
ans = (ans + tm * x * c[i] % M) % M;
}
return (ans + M) % M;
}
static vec ReedsSloane(const vec& s, int64 mod)
{
auto inverse = [](int64 a, int64 m) {
int64 d, x, y;
exgcd(a, m, d, x, y);
return d == ? (x % m + m) % m : -;
};
auto L = [](const vec& a, const vec& b) {
int da = (a.size() > || (a.size() == && a[])) ? a.size() - : -;
int db = (b.size() > || (b.size() == && b[])) ? b.size() - : -;
return std::max(da, db + );
};
auto prime_power = [&](const vec& s, int64 mod, int64 p, int64 e) {
// linear feedback shift register mod p^e, p is prime
std::vector<vec> a(e), b(e), an(e), bn(e), ao(e), bo(e);
vec t(e), u(e), r(e), to(e, ), uo(e), pw(e + );
;
pw[] = ;
for (int i = pw[] = ; i <= e; ++i) pw[i] = pw[i - ] * p;
for (int64 i = ; i < e; ++i)
{
a[i] = {pw[i]}, an[i] = {pw[i]};
b[i] = {}, bn[i] = {s[] * pw[i] % mod};
t[i] = s[] * pw[i] % mod;
if (t[i] == )
{
t[i] = , u[i] = e;
}
else
{
for (u[i] = ; t[i] % p == ; t[i] /= p, ++u[i])
;
}
}
for (size_t k = ; k < s.size(); ++k)
{
for (int g = ; g < e; ++g)
{
if (L(an[g], bn[g]) > L(a[g], b[g]))
{
ao[g] = a[e - - u[g]];
bo[g] = b[e - - u[g]];
to[g] = t[e - - u[g]];
uo[g] = u[e - - u[g]];
r[g] = k - ;
}
}
a = an, b = bn;
for (int o = ; o < e; ++o)
{
int64 d = ;
for (size_t i = ; i < a[o].size() && i <= k; ++i)
{
d = (d + a[o][i] * s[k - i]) % mod;
}
if (d == )
{
t[o] = , u[o] = e;
}
else
{
for (u[o] = , t[o] = d; t[o] % p == ; t[o] /= p, ++u[o])
;
int g = e - - u[o];
if (L(a[g], b[g]) == )
{
extand(bn[o], k + );
bn[o][k] = (bn[o][k] + d) % mod;
}
else
{
int64 coef = t[o] * inverse(to[g], mod) % mod * pw[u[o] - uo[g]] % mod;
int m = k - r[g];
extand(an[o], ao[g].size() + m);
extand(bn[o], bo[g].size() + m);
for (size_t i = ; i < ao[g].size(); ++i)
{
an[o][i + m] -= coef * ao[g][i] % mod;
if (an[o][i + m] < ) an[o][i + m] += mod;
}
while (an[o].size() && an[o].back() == ) an[o].pop_back();
for (size_t i = ; i < bo[g].size(); ++i)
{
bn[o][i + m] -= coef * bo[g][i] % mod;
if (bn[o][i + m] < ) bn[o][i + m] -= mod;
}
while (bn[o].size() && bn[o].back() == ) bn[o].pop_back();
}
}
}
}
return std::make_pair(an[], bn[]);
}; std::vector<std::tuple<int64, int64, int>> fac;
for (int64 i = ; i * i <= mod; ++i)
{
if (mod % i == )
{
int64 cnt = , pw = ;
while (mod % i == ) mod /= i, ++cnt, pw *= i;
fac.emplace_back(pw, i, cnt);
}
}
if (mod > ) fac.emplace_back(mod, mod, );
std::vector<vec> as;
size_t n = ;
for (auto&& x : fac)
{
int64 mod, p, e;
vec a, b;
std::tie(mod, p, e) = x;
auto ss = s;
for (auto&& x : ss) x %= mod;
std::tie(a, b) = prime_power(ss, mod, p, e);
as.emplace_back(a);
n = std::max(n, a.size());
}
vec a(n), c(as.size()), m(as.size());
for (size_t i = ; i < n; ++i)
{
for (size_t j = ; j < as.size(); ++j)
{
m[j] = std::get<>(fac[j]);
c[j] = i < as[j].size() ? as[j][i] : ;
}
a[i] = crt(c, m);
}
return a;
} LinearRecurrence(const vec& s, const vec& c, int64 mod) : init(s), trans(c), mod(mod), m(s.size()) {}
LinearRecurrence(const vec& s, int64 mod, bool is_prime = true) : mod(mod)
{
vec A;
if (is_prime)
A = BerlekampMassey(s, mod);
else
A = ReedsSloane(s, mod);
if (A.empty()) A = {};
m = A.size() - ;
trans.resize(m);
for (int i = ; i < m; ++i)
{
trans[i] = (mod - A[i + ]) % mod;
}
std::reverse(trans.begin(), trans.end());
init = {s.begin(), s.begin() + m};
}
int64 calc(int64 n)
{
if (mod == ) return ;
if (n < m) return init[n];
vec v(m), u(m << );
int msk = !!n;
for (int64 m = n; m > ; m >>= ) msk <<= ;
v[] = % mod;
for (int x = ; msk; msk >>= , x <<= )
{
std::fill_n(u.begin(), m * , );
x |= !!(n & msk);
if (x < m)
u[x] = % mod;
else
{ // can be optimized by fft/ntt
for (int i = ; i < m; ++i)
{
for (int j = , t = i + (x & ); j < m; ++j, ++t)
{
u[t] = (u[t] + v[i] * v[j]) % mod;
}
}
for (int i = m * - ; i >= m; --i)
{
for (int j = , t = i - m; j < m; ++j, ++t)
{
u[t] = (u[t] + trans[j] * u[i]) % mod;
}
}
}
v = {u.begin(), u.begin() + m};
}
int64 ret = ;
for (int i = ; i < m; ++i)
{
ret = (ret + v[i] * init[i]) % mod;
}
return ret;
} vec init, trans;
int64 mod;
int m;
};
using namespace std;
typedef long long ll;
ll A[];
ll mod=1e9;
void init()
{
A[]=A[]=;
A[]=;
for(int i=;i<=;i++){
A[i]=(A[i-]+A[i-])%mod;
}
}
ll qp(ll x,ll n)
{
ll ans=;
while(n){
if(n&)ans=(ans*x)%mod;
x=(x*x)%mod;
n>>=;
}
return ans;
}
int main()
{
init();
ll n,m;
scanf("%lld%lld",&n,&m);
vector<ll> v;
ll t=;
for(int i=;i<=min(n,50ll);i++){
t=(t+qp(A[i],m))%mod;
v.push_back(t);
}
LinearRecurrence L(v, mod, false);
cout<<L.calc(n)<<'\n'; }

BM板子的更多相关文章

  1. ZZNU 2182 矩阵dp (矩阵快速幂+递推式 || 杜教BM)

    题目链接:http://47.93.249.116/problem.php?id=2182 题目描述 河神喜欢吃零食,有三种最喜欢的零食,鱼干,猪肉脯,巧克力.他每小时会选择一种吃一包. 不幸的是,医 ...

  2. 【hdu6185】Covering(骨牌覆盖)

    2017ACM/ICPC广西邀请赛-重现赛1004Covering 题意 n*4的格子,用1*2和2*1的砖块覆盖.问方案数(mod 1e9+7).(n不超过1e9) 题解 递推了个式子然后错位相减. ...

  3. Berlekamp-Massey算法简单介绍

    请阅读本文的同学们注意:之前这篇博客和所附代码有点问题,求的不一定是最短递推式,非常抱歉 看毛爷爷的论文大概断断续续看了一个月了,看得不是很懂,google了一波好像很快就看懂了,就先口胡一下这个算法 ...

  4. ProjectEuler654

    我,ycl:BM是什么早就忘了! 毕老爷:那你们可以做一做这道题练练BM板子啊. 传送门 //Achen #include<bits/stdc++.h> #define For(i,a,b ...

  5. 2017多校Round10(hdu6171~hdu6181)

    补题进度:5/11 1001(双向BFS) 题意: 给你一个类似移子游戏,给你初始状态和终止状态,问初始状态到终止状态至少要移多少步,如果步数>20就-1 分析: 很明显的BFS了,不过普通的B ...

  6. 2018南京区域赛G题 Pyramid——找规律&&递推

    先手动推出前10项,再上BM板子求出递推式 $A_n = 5A_{n-1} - 10A_{n-2} + 10A_{n-3} - 5A_{n-4} + A_{n-5}$,根据特征根理论可求出特征方程 $ ...

  7. NOIp2018集训test-9-7(pm) (联考一day1)

    又被辉神吊打了.今天不仅被辉神李巨吊打,还给基本上给全班垫底了. 看到T3就知道是十进制快速幂,全机房考试的当时应该就我会,结果我tm没找到递推. Orz lyc BM直接水过,Orz wys六个fo ...

  8. 杜教BM递推板子

    Berlekamp-Massey 算法用于求解常系数线性递推式 #include<bits/stdc++.h> typedef std::vector<int> VI; typ ...

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

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

随机推荐

  1. 创建一个项目并在GitHub上发出拉取请求

    1.第一步:创建存储库 创建新存储库: New repository 命名存储库 写一个简短的描述 选择使用自述文件初始化此存储库 2.第二步:创建一个分支 创建一个新分支 转到新的存储库hello- ...

  2. [转帖]是时候深入了解Linux的系统结构

    是时候深入了解Linux的系统结构   http://os.51cto.com/art/201905/596011.htm linux的体系结果 其实自己也知道 linus 做了一个 kernel 大 ...

  3. [19/06/05-星期三] CSS基础_样式表的位置(内联、内部、外部样式)、块元素(div)、内联元素(span)、常用的选择器

    一.概念 CSS(Cascading Style Sheets,层叠样式表) 可以用来为网页创建样式表,通过样式表可以对网页进行装饰. 所谓层叠,就是可以将整个网页想象成是一层一层的结构,层次高的将会 ...

  4. 小白学Python——Matplotlib 学习(3) 函数图形

    import matplotlib.pyplot as plt import numpy as np x = np.linspace(-1,1,50) y = 2*x + 1 plt.figure() ...

  5. kotlin学习(8)泛型

    泛型的声明 与Java不同的是,Kotlin要求类型实参要么被显示的说明,要么能被编译器推导出来.因为Java在1.5版本才引入泛型,所以为了兼容过去的版本,可以不直接声明List类型的变量,而不说明 ...

  6. Python字符串中添加、插入特定字符

    分析 我们将添加.插入.删除定义为: 添加: 在字符串的后面或者前面添加字符或者字符串 插入: 在字符串之间插入特定字符 在Python中,字符串是不可变的.所以无法直接删除.插入字符串之间的特定字符 ...

  7. TMS320F28335——SPI使用笔记

    一.SPI硬件接口 GPIO54    -------    SPISIMOA GPIO55    -------    SPISOMIA GPIO56    -------    SPCLK GPI ...

  8. C++泛型程序设计---算法和提升

    算法和提升 算法:所谓算法就是一个求解问题的过程或公式,即,通过一个有穷的计算序列生成结果. 函数模板就是普通函数的泛化:它能对多种数据类型执行动作,并且能用以参数方式传递来的各种操作实现要执行的工作 ...

  9. 豆壳CMS本地安装教程

    DouPHP安装教程 一.下载DouPHP程序. 解压后得到三个文件夹 将upload文件夹里面的内容复制到wamp的www的文件夹. 二.打开浏览器,输入127.0.0.1. 勾选后选择下一步 注意 ...

  10. 关于Mysql select语句中拼接字符串的记录

    在mysql的SELECT语句中拼接两列(或多列)的字符串显示: mysql> select concat(dname,loc) from dept; 以上语句便把dept表的dname,loc ...