BM板子
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项
#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板子的更多相关文章
- ZZNU 2182 矩阵dp (矩阵快速幂+递推式 || 杜教BM)
题目链接:http://47.93.249.116/problem.php?id=2182 题目描述 河神喜欢吃零食,有三种最喜欢的零食,鱼干,猪肉脯,巧克力.他每小时会选择一种吃一包. 不幸的是,医 ...
- 【hdu6185】Covering(骨牌覆盖)
2017ACM/ICPC广西邀请赛-重现赛1004Covering 题意 n*4的格子,用1*2和2*1的砖块覆盖.问方案数(mod 1e9+7).(n不超过1e9) 题解 递推了个式子然后错位相减. ...
- Berlekamp-Massey算法简单介绍
请阅读本文的同学们注意:之前这篇博客和所附代码有点问题,求的不一定是最短递推式,非常抱歉 看毛爷爷的论文大概断断续续看了一个月了,看得不是很懂,google了一波好像很快就看懂了,就先口胡一下这个算法 ...
- ProjectEuler654
我,ycl:BM是什么早就忘了! 毕老爷:那你们可以做一做这道题练练BM板子啊. 传送门 //Achen #include<bits/stdc++.h> #define For(i,a,b ...
- 2017多校Round10(hdu6171~hdu6181)
补题进度:5/11 1001(双向BFS) 题意: 给你一个类似移子游戏,给你初始状态和终止状态,问初始状态到终止状态至少要移多少步,如果步数>20就-1 分析: 很明显的BFS了,不过普通的B ...
- 2018南京区域赛G题 Pyramid——找规律&&递推
先手动推出前10项,再上BM板子求出递推式 $A_n = 5A_{n-1} - 10A_{n-2} + 10A_{n-3} - 5A_{n-4} + A_{n-5}$,根据特征根理论可求出特征方程 $ ...
- NOIp2018集训test-9-7(pm) (联考一day1)
又被辉神吊打了.今天不仅被辉神李巨吊打,还给基本上给全班垫底了. 看到T3就知道是十进制快速幂,全机房考试的当时应该就我会,结果我tm没找到递推. Orz lyc BM直接水过,Orz wys六个fo ...
- 杜教BM递推板子
Berlekamp-Massey 算法用于求解常系数线性递推式 #include<bits/stdc++.h> typedef std::vector<int> VI; typ ...
- 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)
这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...
随机推荐
- Java第五周作业+总结
实验三 String类的应用 实验目的 掌握类String类的使用: 学会使用JDK帮助文档: 实验内容 1.已知字符串:"this is a test of java".按要求执 ...
- (ROT-13解密)Flare-On4: Challenge1 login.html
说是FlareOn的逆向 倒不如说是crypto....... 题目不难 F12看源码: document.getElementById("prompt").onclick = f ...
- SCUT - 486 - 无向图上的点 - Dijkstra
好像原题是这个?https://www.cnblogs.com/kanchuang/p/11120052.html 这个有解释:https://blog.csdn.net/wddwjlss/artic ...
- 00.AutoMapper 之入门指南(Getting Started Guide)
转载(https://www.jianshu.com/p/29ee5a94c1d9) 入门指南(Getting Started Guide) AutoMapper 是什么? AutoMapper 是一 ...
- js常见的设计模式一
1.观察者模式 定义一些一对多的关系,将一系列的观察者对目标函数感兴趣,将自己添加进目标函数,当目标函数状态发生改变时,发送通知,以此通知附加在目标上的观察者 /* 目标 */ class subje ...
- Site error: the ionCube PHP Loader needs to be installed.解决办法
问题描述: 有些模块的作者为了保护代码而采用ionCube加密的代码,所以这里必须给服务器装上这个php的扩展,就好像以前的zend一样 解决办法: http://bbs.52jscn.com/thr ...
- loadkeys - 调入键盘翻译表
总览 (SYNOPSIS) loadkeys [ -d --default ] [ -h --help ] [ -q --quiet ] [ -v --verbose [ -v --verbose ] ...
- 023-OpenStack 创建实例类型临时磁盘的讲解
临时磁盘占用的那块磁盘的空间查看 [root@linux-node1 dev]# fdisk -l 磁盘 /dev/sdb:26.8 GB, 26843545600 字节,52428800 个扇区 U ...
- c语言之ascii字符
int main(){ char buf[20] = {104,101,108,108,111,0}; printf("buf:%s\n",buf); return 0;} 打印结 ...
- jemter简单测试方式
一.简介 Jmeter是一款优秀的开源测试工具, 是每个资深测试工程师,必须掌握的测试工具,熟练使用Jmeter能大大提高工作效率. **开源,他是一款开源的免费软件,使用它你不需要支付任何费用, * ...