[数学记录]51nod1236 序列求和 V3

command_block

2020-11-20 21:59:37

Personal

**题意** : 设 $F[n]$ 为斐波那契数列的第 $n$ 项。 给出 $n,k$ ,求下列式子的值 : $$\sum\limits_{i=1}^nF[i]^k$$ 答案对 $10^9+9$ 取模。 多组数据,$T\leq 10,n\leq 10^{18},k\leq 10^5$,时限 $\texttt{6s}$。 ------------ 考虑斐波那契数列的通项公式 : $$F[n]=\dfrac{\sqrt{5}}{5}\left[\left(\frac{1+\sqrt{5}}{2}\right)^{n}-\left(\frac{1-\sqrt{5}}{2}\right)^{n}\right]$$ 方便起见,设 $r=\frac{\sqrt{5}}{5},a=\frac{1+\sqrt{5}}{2},b=\frac{1-\sqrt{5}}{2}$ ,则 $F[n]=r(a^n-b^n)$。 附 : $\sqrt{5}=383008016\pmod{10^9+9}$。 ${\rm Ans}=\sum\limits_{i=1}^nF[i]^k$ $=\sum\limits_{i=1}^n\big(r(a^i-b^i)\big)^k$ $=\sum\limits_{i=1}^nr^k\sum\limits_{j=0}^k\dbinom{k}{j}a^{ij}(-b^{i})^{(k-j)}$ $=r^k\sum\limits_{j=0}^k\dbinom{k}{j}(-1)^{k-j}\sum\limits_{i=1}^n(a^{j}b^{k-j})^{i}$ 后半部等比数列求和即可,复杂度 $O(k\log n)$。 ```cpp #include<algorithm> #include<cstdio> #define ll long long #define MaxN 100500 using namespace std; int mod=1000000009,w=383008016; ll powM(ll a,int t=mod-2){ ll ret=1; while(t){ if (t&1)ret=ret*a%mod; a=a*a%mod;t>>=1; }return ret; } ll fac[MaxN],ifac[MaxN],pwa[MaxN],pwb[MaxN]; void Init(int n) { fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod; ifac[n]=powM(fac[n]); for (int i=n;i;i--) ifac[i-1]=ifac[i]*i%mod; ll a=(1+w)*powM(2)%mod ,b=(1-w)*powM(2)%mod; pwa[0]=pwb[0]=1; for (int i=1;i<=n;i++){ pwa[i]=pwa[i-1]*a%mod; pwb[i]=pwb[i-1]*b%mod; } } ll S(ll a,ll n){ if (a==1)return n%mod; return a*(powM(a,n%(mod-1))-1)%mod*powM(a-1)%mod; } void solve(ll n,int k) { ll ans=0; for (int i=0;i<=k;i++){ ll buf=ifac[i]*ifac[k-i]%mod*S(pwa[i]*pwb[k-i]%mod,n); if ((k-i)&1)ans=(ans-buf)%mod; else ans=(ans+buf)%mod; }ans=(ans+mod)%mod; printf("%lld\n",ans*fac[k]%mod*powM(w,mod-1-k)%mod); } ll n[15];int T,k[15],lim; int main() { scanf("%d",&T); for (int i=1;i<=T;i++){ scanf("%lld%d",&n[i],&k[i]); lim=max(lim,k[i]); }Init(lim); for (int i=1;i<=T;i++) solve(n[i],k[i]); return 0; } ```