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. Python web 面试题(一)

    1.列举django的内置组件? url .view.model.template.中间件 2.列举django中间件的5个方法?以及django中间件的应用场景? process_request(s ...

  2. java锁的使用

    1 synchronize和ReentrantLock synchronize锁是jvm内置的锁,它锁的是synchronize所在的类的对象,要同步那么就只能有一个对象. ReentrantLock ...

  3. Maven 项目中的groupId和artifactId

    maven进行项目管理,如果我们要将项目加入到maven到本地仓库中,则需要对项目进行唯一性标示,而groupId和artifactId就起到这样对作用. groupId为项目组织对唯一标识符,可以理 ...

  4. S-Nim HDU 1536 博弈 sg函数

    S-Nim HDU 1536 博弈 sg函数 题意 首先输入K,表示一个集合的大小,之后输入集合,表示对于这对石子只能去这个集合中的元素的个数,之后输入 一个m表示接下来对于这个集合要进行m次询问,之 ...

  5. 区间gcd

    http://codeforces.com/problemset/problem/914/D 题意:给你n个数,两种操作:1.询问区间[l,r]在至多一次修改一个数的条件下区间gcd是否等于x. 2. ...

  6. CSP-J&S 2019游记

    $Day -???$ 和爱国爱党的$LQX$书记打了个赌,谁$TG$分低请另一个京味斋. $Day 0$ 机房同学去聚餐,美其名曰"散伙饭",可能又有几个进队的... 我没有去,因 ...

  7. IBM公司面试题

    进入IBM差不多是每一个IT人的梦想.IBM公司向来以高素质人才作为企业持续竞争力的保证,所以经常出一些千奇百怪的面试题,来考验一个人的综合能力,以下是5道IBM曾经出过的面试题,看看你能作出几道:  ...

  8. 自动化部署三剑客 gitlab + ansible + jenkins

    http://www.showerlee.com/archives/1880 https://edu.51cto.com/center/course/lesson/index?id=280700 Gi ...

  9. GROUP BY关键字优化

    1.group by实质是先排序后进行分组,遵照索引建的最佳左前缀 2.当无法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置 ...

  10. netperf编译./configure时报错 "error: cannot guess build type;you nust specify one"

    问题: 解决办法-亲测可用: 尝试:./configure --build=mingw提示无法辨别 checking build system type... Invalid configuratio ...