# !Берликамп (OEIS во плоти)

Apr 18th, 2019
184
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. #include <bits/stdc++.h>
2. using namespace std;
3. #define pb push_back
4. typedef long long ll;
5. #define SZ 233333
6. const int MOD=1e9+7; //or any prime
7. ll qp(ll a,ll b)
8. {
9.     ll x=1; a%=MOD;
10.     while(b)
11.     {
12.         if(b&1) x=x*a%MOD;
13.         a=a*a%MOD; b>>=1;
14.     }
15.     return x;
16. }
17. namespace linear_seq {
18. inline vector<int> BM(vector<int> x)
19. {
20.     //ls: (shortest) relation sequence (after filling zeroes) so far
21.     //cur: current relation sequence
22.     vector<int> ls,cur;
23.     //lf: the position of ls (t')
24.     //ld: delta of ls (v')
25.     int lf,ld;
26.     for(int i=0;i<int(x.size());++i)
27.     {
28.         ll t=0;
29.         //evaluate at position i
30.         for(int j=0;j<int(cur.size());++j)
31.             t=(t+x[i-j-1]*(ll)cur[j])%MOD;
32.         if((t-x[i])%MOD==0) continue; //good so far
33.         //first non-zero position
34.         if(!cur.size())
35.         {
36.             cur.resize(i+1);
37.             lf=i; ld=(t-x[i])%MOD;
38.             continue;
39.         }
40.         //cur=cur-c/ld*(x[i]-t)
41.         ll k=-(x[i]-t)*qp(ld,MOD-2)%MOD/*1/ld*/;
42.         vector<int> c(i-lf-1); //add zeroes in front
43.         c.pb(k);
44.         for(int j=0;j<int(ls.size());++j)
45.             c.pb(-ls[j]*k%MOD);
46.         if(c.size()<cur.size()) c.resize(cur.size());
47.         for(int j=0;j<int(cur.size());++j)
48.             c[j]=(c[j]+cur[j])%MOD;
49.         //if cur is better than ls, change ls to cur
50.         if(i-lf+(int)ls.size()>=(int)cur.size())
51.             ls=cur,lf=i,ld=(t-x[i])%MOD;
52.         cur=c;
53.     }
54.     for(int i=0;i<int(cur.size());++i)
55.         cur[i]=(cur[i]%MOD+MOD)%MOD;
56.     return cur;
57. }
58. int m; //length of recurrence
59. //a: first terms
60. //h: relation
61. ll a[SZ],h[SZ],t_[SZ],s[SZ],t[SZ];
62. //calculate p*q mod f
63. inline void mull(ll*p,ll*q)
64. {
65.     for(int i=0;i<m+m;++i) t_[i]=0;
66.     for(int i=0;i<m;++i) if(p[i])
67.         for(int j=0;j<m;++j)
68.             t_[i+j]=(t_[i+j]+p[i]*q[j])%MOD;
69.     for(int i=m+m-1;i>=m;--i) if(t_[i])
70.         //miuns t_[i]x^{i-m}(x^m-\sum_{j=0}^{m-1} x^{m-j-1}h_j)
71.         for(int j=m-1;~j;--j)
72.             t_[i-j-1]=(t_[i-j-1]+t_[i]*h[j])%MOD;
73.     for(int i=0;i<m;++i) p[i]=t_[i];
74. }
75. inline ll calc(ll K)
76. {
77.     for(int i=m;~i;--i)
78.         s[i]=t[i]=0;
79.     //init
80.     s[0]=1; if(m!=1) t[1]=1; else t[0]=h[0];
81.     //binary-exponentiation
82.     while(K)
83.     {
84.         if(K&1) mull(s,t);
85.         mull(t,t); K>>=1;
86.     }
87.     ll su=0;
88.     for(int i=0;i<m;++i) su=(su+s[i]*a[i])%MOD;
89.     return (su%MOD+MOD)%MOD;
90. }
91. inline int work(vector<int> x,ll n)
92. {
93.     if(n<int(x.size())) return x[n];
94.     vector<int> v=BM(x); m=v.size(); if(!m) return 0;
95.     for(int i=0;i<m;++i) h[i]=v[i],a[i]=x[i];
96.     return calc(n);
97. }
98. }
99. using linear_seq::work;
100. int main()
101. {
102.     vector<int> x = {1, 2, 4, 8, 16};
103.     for (int i = 0; i < 10; i++)
104.         cout << work(x, i) << endl;
105. }
RAW Paste Data