线性递推式(外挂)

传入前几项,输出低n项的值

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <string>
 7 #include <map>
 8 #include <set>
 9 #include <cassert>
10 using namespace std;
11 #define rep(i,a,n) for (int i=a;i<n;i++)
12 #define per(i,a,n) for (int i=n-1;i>=a;i--)
13 #define pb push_back
14 #define mp make_pair
15 #define all(x) (x).begin(),(x).end()
16 #define fi first
17 #define se second
18 #define SZ(x) ((int)(x).size())
19 typedef vector<int> VI;
20 typedef long long ll;
21 typedef pair<int,int> PII;
22 const ll mod=1000000007;
23 ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
24 // head
25
26 int _,n;
27 namespace linear_seq {
28     const int N=10010;
29     ll res[N],base[N],_c[N],_md[N];
30
31     vector<int> Md;
32     void mul(ll *a,ll *b,int k) {
33         rep(i,0,k+k) _c[i]=0;
34         rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
35         for (int i=k+k-1;i>=k;i--) if (_c[i])
36             rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
37         rep(i,0,k) a[i]=_c[i];
38     }
39     int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
40 //        printf("%d\n",SZ(b));
41         ll ans=0,pnt=0;
42         int k=SZ(a);
43         assert(SZ(a)==SZ(b));
44         rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
45         Md.clear();
46         rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
47         rep(i,0,k) res[i]=base[i]=0;
48         res[0]=1;
49         while ((1ll<<pnt)<=n) pnt++;
50         for (int p=pnt;p>=0;p--) {
51             mul(res,res,k);
52             if ((n>>p)&1) {
53                 for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
54                 rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
55             }
56         }
57         rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
58         if (ans<0) ans+=mod;
59         return ans;
60     }
61     VI BM(VI s) {
62         VI C(1,1),B(1,1);
63         int L=0,m=1,b=1;
64         rep(n,0,SZ(s)) {
65             ll d=0;
66             rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
67             if (d==0) ++m;
68             else if (2*L<=n) {
69                 VI T=C;
70                 ll c=mod-d*powmod(b,mod-2)%mod;
71                 while (SZ(C)<SZ(B)+m) C.pb(0);
72                 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
73                 L=n+1-L; B=T; b=d; m=1;
74             } else {
75                 ll c=mod-d*powmod(b,mod-2)%mod;
76                 while (SZ(C)<SZ(B)+m) C.pb(0);
77                 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
78                 ++m;
79             }
80         }
81         return C;
82     }
83     int gao(VI a,ll n) {
84         VI c=BM(a);
85         c.erase(c.begin());
86         rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
87         return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
88     }
89 };
90
91 int main(){
92     //for (scanf("%d",&_);_;_--) {
93         while(scanf("%d",&n)!=EOF){
94             printf("%d\n",linear_seq::gao(VI{1,2,4,7,13,24},n-1));
95         }
96     //}
97 }
时间: 2024-12-25 07:00:30

线性递推式(外挂)的相关文章

bzoj4161 (k^2logn求线性递推式)

分析: 我们可以写把转移矩阵A写出来,然后求一下它的特征多项式,经过手动计算应该是这样的p(x)=$x^k-\sum\limits_{i=1}^ka_i*x^{k-i}$ 根据Cayley-Hamilton定理可得,p(A)=0 他表示$A^n = f(A) * p(A) + g(A)$ 第一项的值是0,所以即$A^n=g(A)$,其中f(A) g(A)都是关于A的多项式,f(A)是多项式除法的商,g(A)是余数 我们考虑$x^n$这个多项式,我们去求出它对于$p(A)$的余数多项式$g(A)$

[HDOJ6172] Array Challenge(线性递推,黑科技)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6172 题意:给一堆东西,就是求个线性递推式,求第n项%1e9+7 杜教板真牛逼啊,线性递推式用某特征值相关的论文板,打表前几项丢进去就出结果了. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 #define rep(i,a,n) for (ll i=a;i<n;i++) 6 #def

算法分析中递推式的一般代数解法 张洋

http://blog.codinglabs.org/articles/linear-algebra-for-recursion.html 另介绍一种算法 Berlekamp-Massey算法,常简称为BM算法,是用来求解一个数列的最短线性递推式的算法. #include <bits/stdc++.h> using namespace std; typedef long long ll; const double eps = 1e-7; const int maxn = 1e5 + 5; ve

hdu 1757 A Simple Math Problem (构造矩阵解决递推式问题)

题意:有一个递推式f(x) 当 x < 10    f(x) = x.当 x >= 10  f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10) 同时ai(0<=i<=9) 不是 0 就是 1: 现在给你 ai 的数字,以及k和mod,请你算出 f(x)%mod 的结果是多少 思路:线性递推关系是组合计数中常用的一种递推关系,如果直接利用递推式,需要很长的时间才能计算得出,时间无法承受,但是现在我们已知

递推式转化为矩阵形式

EXAMPLE: 递推式: d(n + 2) = p * d(n + 1) + (1 - p) * d(n); 令G(n) = (d(n + 2), d(n + 1))^T; 则 G(n + 1) = M * G(n); 解得 M = p   1 - p 1    0 G(n) = (M ^ n) * G(0); #

多校第九场:贪心+矩阵快速幂中间优化+线性递推&amp;线段树递推

HDU 4968 Improving the GPA 思路:贪心的搞吧!比赛的时候想了好久,然后才发现了点规律,然后乱搞1A. 因为贪心嘛!大的情况就是刚开始每个人的分数都是最大的最小值,即绩点4.0的最低分数85,然后最后一个数设为剩余的分数,然后如果小于60就从第一个分数补到这个分数来,然后最后一个分数还小于60,那就用第二个补--依次往下搞,那时我也不知道这样就搞出答案了,我还没证明这个对不对呢,哈哈. 小的情况:小的情况就是先假设每个人都是绩点最小的最大分数,即绩点2.0的最大分数69,

hiho 1143 矩阵快速幂 求递推式

题目链接: hihocoder 1143 思路见题目上 快速幂模板: // m^n % k int quickpow(int m,int n,int k) { int b = 1; while (n > 0) { if (n & 1) b = (b*m)%k; n = n >> 1 ; m = (m*m)%k; } return b; } 题解: #include<iostream> #include<cstdio> #include<cstring

矩阵乘法优化线性递推

矩阵乘法是线性代数中一块很重要的内容.矩阵乘法的定义很奇怪[1],但正是这种奇怪的性质,让矩阵乘法成为在除了线性代数和其衍生学科(还有诸如矩阵力学之类)外最广泛使用的关于矩阵变换的应用.(什么?FFT不属于矩阵变换吧...) 注: [1]: 矩阵乘法有另外的很多定义,如未说明,指的是中间不带符号的矩阵乘法,即一般矩阵乘积.另有 标量乘积(即所有数乘上一个固定的数),阿达马乘积等,没有那么诡异,但是在大多数问题的用途上也不大. 你不会矩阵乘法?没关系,下一篇会写到的 矩阵乘法的本质 矩阵乘法的本质

利用Cayley-Hamilton theorem 优化矩阵线性递推

平时有关线性递推的题,很多都可以利用矩阵乘法来解k决. 时间复杂度一般是O(K3logn)因此对矩阵的规模限制比较大. 下面介绍一种利用利用Cayley-Hamilton theorem加速矩阵乘法的方法. Cayley-Hamilton theorem: 记矩阵A的特征多项式为f(x). 则有f(A)=0. 证明可以看 维基百科 https://en.wikipedia.org/wiki/Cayley–Hamilton_theorem#A_direct_algebraic_proof 另外我在