Advertisement
peltorator

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

Apr 18th, 2019
408
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.44 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement