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

Posted tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 #define per(i,a,n) for (ll i=n-1;i>=a;i--)
 7 #define pb push_back
 8 #define mp make_pair
 9 #define all(x) (x).begin(),(x).end()
10 #define fi first
11 #define se second
12 #define SZ(x) ((ll)(x).size())
13 typedef vector<ll> VI;
14 typedef pair<ll,ll> PII;
15 const ll mod=1000000007;
16 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;}
17 // head
18 
19 ll _,n;
20 namespace linear_seq {
21     const ll N=10010;
22     ll res[N],base[N],_c[N],_md[N];
23 
24     vector<ll> Md;
25     void mul(ll *a,ll *b,ll k) {
26         rep(i,0,k+k) _c[i]=0;
27         rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
28         for (ll i=k+k-1;i>=k;i--) if (_c[i])
29             rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
30         rep(i,0,k) a[i]=_c[i];
31     }
32     ll solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
33 //        printf("%d\n",SZ(b));
34         ll ans=0,pnt=0;
35         ll k=SZ(a);
36         assert(SZ(a)==SZ(b));
37         rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
38         Md.clear();
39         rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
40         rep(i,0,k) res[i]=base[i]=0;
41         res[0]=1;
42         while ((1ll<<pnt)<=n) pnt++;
43         for (ll p=pnt;p>=0;p--) {
44             mul(res,res,k);
45             if ((n>>p)&1) {
46                 for (ll i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
47                 rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
48             }
49         }
50         rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
51         if (ans<0) ans+=mod;
52         return ans;
53     }
54     VI BM(VI s) {
55         VI C(1,1),B(1,1);
56         ll L=0,m=1,b=1;
57         rep(n,0,SZ(s)) {
58             ll d=0;
59             rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
60             if (d==0) ++m;
61             else if (2*L<=n) {
62                 VI T=C;
63                 ll c=mod-d*powmod(b,mod-2)%mod;
64                 while (SZ(C)<SZ(B)+m) C.pb(0);
65                 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
66                 L=n+1-L; B=T; b=d; m=1;
67             } else {
68                 ll c=mod-d*powmod(b,mod-2)%mod;
69                 while (SZ(C)<SZ(B)+m) C.pb(0);
70                 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
71                 ++m;
72             }
73         }
74         return C;
75     }
76     ll gao(VI a,ll n) {
77         VI c=BM(a);
78         c.erase(c.begin());
79         rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
80         return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
81     }
82 };
83 
84 signed main() {
85     // freopen("in", "r", stdin);
86     for (scanf("%lld",&_);_;_--) {
87         scanf("%lld",&n);
88         printf("%lld\n",linear_seq::gao(VI{31,197,1255,7997,50959,324725,2069239,13185773,84023455},n-2));
89     }
90 }

 

以上是关于[HDOJ6172] Array Challenge(线性递推,黑科技)的主要内容,如果未能解决你的问题,请参考以下文章

2017多校第10场 HDU 6172 Array Challenge 猜公式,矩阵幂

HDU - 6172:Array Challenge (BM线性递推)

HDOJ 5653 Bomber Man wants to bomb an Array.(DP)

hdoj6703 2019 CCPC网络选拔赛 1002 array

HDOJ5532Almost Sorted Array(签到)

hdoj-3791-二叉搜索树(二叉搜索树模板题)