ACM-ICPC 2018 焦作賽區網路預賽L(BM遞推杜教版)
阿新 • • 發佈:2018-12-10
...講道理,這板子是真的牛逼
#include <cstdio> #include <cstdlib> #include <cassert> #include <cstring> #include <bitset> #include <cmath> #include <cctype> #include <unordered_map> #include <iostream> #include <algorithm> #include <string> #include <vector> #include <queue> #include <map> #include <set> #include <sstream> #include <iomanip> using namespace std; typedef long long ll; typedef vector<long long> VI; typedef unsigned long long ull; const ll inff = 0x3f3f3f3f3f3f3f3f; #define FOR(i,a,b) for(int i(a);i<=(b);++i) #define FOL(i,a,b) for(int i(a);i>=(b);--i) #define SZ(x) ((long long)(x).size()) #define REW(a,b) memset(a,b,sizeof(a)) #define inf int(0x3f3f3f3f) #define si(a) scanf("%d",&a) #define sl(a) scanf("%I64d",&a) #define sd(a) scanf("%lf",&a) #define ss(a) scanf("%s",a) #define mod ll(1e9+7) #define pb push_back #define eps 1e-6 #define lc d<<1 #define rc d<<1|1 #define Pll pair<ll,ll> #define P pair<int,int> #define pi acos(-1) ll powmod(ll a,ll b) { ll res=1ll; while(b) { if(b&1) res=res*a%mod; a=a*a%mod,b>>=1; } return res; } namespace linear_seq { const int N=10010; ll res[N],base[N],_c[N],_md[N]; vector<int> Md; void mul(ll *a,ll *b,int k) { FOR(i,0,k+k-1) _c[i]=0; FOR(i,0,k-1) if (a[i]) FOR(j,0,k-1) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod; for (int i=k+k-1;i>=k;i--) if (_c[i]) FOR(j,0,SZ(Md)-1) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod; FOR(i,0,k-1) a[i]=_c[i]; } int solve(ll n,VI a,VI b) { // a 係數 b 初值 b[n+1]=a[0]*b[n]+... // printf("%d\n",SZ(b)); ll ans=0,pnt=0; int k=SZ(a); assert(SZ(a)==SZ(b)); FOR(i,0,k-1) _md[k-1-i]=-a[i];_md[k]=1; Md.clear(); FOR(i,0,k-1) if (_md[i]!=0) Md.push_back(i); FOR(i,0,k-1) res[i]=base[i]=0; res[0]=1; while ((1ll<<pnt)<=n) pnt++; for (int p=pnt;p>=0;p--) { mul(res,res,k); if ((n>>p)&1) { for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0; FOR(j,0,SZ(Md)-1) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod; } } FOR(i,0,k-1) ans=(ans+res[i]*b[i])%mod; if (ans<0) ans+=mod; return ans; } VI BM(VI s) { VI C(1,1),B(1,1); int L=0,m=1,b=1; FOR(n,0,SZ(s)-1) { ll d=0; FOR(i,0,L) d=(d+(ll)C[i]*s[n-i])%mod; if (d==0) ++m; else if (2*L<=n) { VI T=C; ll c=mod-d*powmod(b,mod-2)%mod; while (SZ(C)<SZ(B)+m) C.pb(0); FOR(i,0,SZ(B)-1) C[i+m]=(C[i+m]+c*B[i])%mod; L=n+1-L; B=T; b=d; m=1; } else { ll c=mod-d*powmod(b,mod-2)%mod; while (SZ(C)<SZ(B)+m) C.pb(0); FOR(i,0,SZ(B)-1) C[i+m]=(C[i+m]+c*B[i])%mod; ++m; } } return C; } int gao(VI a,ll n) { VI c=BM(a); c.erase(c.begin()); FOR(i,0,SZ(c)-1) c[i]=(mod-c[i])%mod; return solve(n,c,VI(a.begin(),a.begin()+SZ(c))); } }; int main() { cin.tie(0); cout.tie(0); ll n,t; cin>>t; while(t--) { scanf("%lld",&n); printf("%lld\n",linear_seq::gao(VI{3,9,20,46,106,244,560,1286,2956,6794,15610},n-1)%mod); } return 0; }