【洛谷4451】[国家集训队] 整数的lqp拆分(生成函数水题)

点此看题面

  • (F(x))为斐波那契数列的生成函数,求(sum_{i=1}^{+infty}F(x)^i)(n)次项系数。
  • (nle10^{10^5})

生成函数

利用等比数列求和公式得到:

[sum_{i=1}^{+infty}F(x)^i=frac{F(x)}{1-F(x)} ]

众所周知(F(x)=frac x{1-x-x^2}),于是原式等价于:

[frac x{1-2x-x^2} ]

然后我们仿照推斐波那契数列通项公式的方式来推一推它的通项公式。(具体方法可详见初学生成函数(二)——生成函数与斐波那契数列,这里就写得简略一些了)

首先把分母变个形得到:

[frac x{(1-Ax)(1-Bx)} ]

解得(A=1+sqrt2,B=1-sqrt2)

然后把它裂开得到:

[frac{frac A{2sqrt2}x}{1-Ax}-frac{frac B{2sqrt2}x}{1-Bx} ]

(Ax,Bx)看作整体反向利用等比数列求和公式得到:

[F(x)=sum_{i=1}^{infty}frac{A^i-B^i}{2sqrt2}x^i ]

所以第(n)项系数为:

[frac{(1+sqrt2)^n-(1-sqrt2)^n}{2sqrt2} ]

在模(10^9+7)意义下有(sqrt2=59713600),那么就可以直接快速幂计算了。

一个小技巧,对于质数(p)(a^nequiv a^{n\%(p-1)}(mod p))恒成立,所以我们可以在读入的同时将(n)(10^9+6),就可以避免高精了。

代码:(O(logX))

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define X 1000000007
#define I2 500000004
#define S2 59713600
using namespace std;
int n;I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int main()
{
	char c;W(!isdigit(c=getchar()));W(n=(10LL*n+(c&15))%(X-1),isdigit(c=getchar()));//读入同时取模
	return printf("%d
",1LL*(QP(1+S2,n)-QP(1-S2+X,n)+X)*QP(S2<<1,X-2)%X),0;//快速幂计算答案
}
原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu4451.html