[国家集训队]整数的lqp拆分

题目

设我们要求的是\(g_n\)

我们强行定义\(g_0=1\)

于是就有

\[g_i=\sum_{j=0}^{i-1}fib_{j}g_{i-j} \]

就是新枚举一个\(j\),通过一个分配率和在原来的答案上更进一步

于是这个数列的生成函数就是

\[\begin{aligned} G(x)=&\sum_{i=0}(\sum_{j=0}^{i-1}fib_jg_{i-j}+[i=0])x^i\\&=1+\sum_{i=0}(\sum_{j=0}^{i-1}fib_jg_{i-j})x^i\\&=1+\sum_{i=0}\sum_{j=0}^{i-1}fib_{j}x_j\times g_{i-j}x^{i-j}\end{aligned} \]

发现里面是\(fib\)的生成函数卷上\(G(x)\)

\[F(x)=\sum_{i=0}fib_ix^i=\frac{x}{1-x-x^2} \]

于是就有

\[G(x)=1+G(x)F(x) \]

解得

\[G(x)=\frac{1-x-x^2}{1-2x-x^2}=\frac{1-2x-x^2+x}{1-2x-x^2}=1+\frac{x}{1-2x-x^2} \]

发现多出来的那个常数项是我们强行使得\(g_0=1\)的结果,不管它就好了

强行处理后面的\(\frac{x}{1-2x-x^2}\)

我们发现分母上可以被因式分解一下

\[\frac{x}{1-2x-x^2}=\frac{x}{(1-(1-\sqrt{2})x)(1-(1+\sqrt{2})x)} \]

你说怎么搞这个因式分解,你把\(1-\sqrt{2}\)设成\(\frac{a\pm\sqrt{b}}{c}\)的形式

就会发现

\[\frac{a+\sqrt{b}}{c}\times \frac{a-\sqrt{b}}{c}=\frac{a^b-b}{c^2}=-1 \]

\[-(\frac{a+\sqrt{b}}{c}+ \frac{a-\sqrt{b}}{c})=-2 \]

根据下面那个式子我们可以发现\(a=c\)

于是上面那个式子就是\(2a^2-b=0\),我们发现只需要使得\(a=1,b=2\)就可以了

于是我们就又需要来拆掉这个式子

至于这个如何去拆,我们可以继续列方程

设上面那个式子等于

\[\begin{aligned}&\frac{a}{1-(1-\sqrt{2})x}+\frac{b}{1-(1+\sqrt{2})x}\\&=\frac{a(1-(1+\sqrt{2})x)+b(1-(1-\sqrt{2})x)}{(1-(1-\sqrt{2})x)(1-(1+\sqrt{2})x)}\\&=\frac{a-ax-a\sqrt{2}x+b-bx+b\sqrt{2}x}{(1-(1-\sqrt{2})x)(1-(1+\sqrt{2})x)}\end{aligned} \]

我们知道上面那一大坨东西应该等于\(x\)

于是

\[a-ax-a\sqrt{2}x+b-bx+b\sqrt{2}x=x \]

由于没有常数项,于是\(a=-b\)

也就有

\[-a\sqrt{2}x+b\sqrt{2}x=x \]

解得\(a=-\frac{1}{2\sqrt{2}},b=\frac{1}{2\sqrt{2}}\),我们\(a,b\)放到外面就好了

可以拆成

\[-\frac{\sqrt{2}}{4}\times\frac{1}{1-(1-\sqrt{2})x}+\frac{\sqrt{2}}{4}\times \frac{1}{1-(1+\sqrt{2})x} \]

发现有两个诸如\(\frac{1}{1-cx}\)的生成函数,这就是一个公比为\(c\)的等比数列

于是我们就可以推出通项

\[g_n=-\frac{\sqrt{2}}{4}\times (1-\sqrt{2})^n+\frac{\sqrt{2}}{4}\times(1+\sqrt{2})^n \]

由于我比较菜,不会二次剩余,可以写个暴力求一下\(x^2 \equiv 2(mod\ 1e9+7)\),发现\(x=59713600\)

根据通项就可以求了,就是一个快速幂的事

#include<cstdio>
#define LL long long
const LL mod=1e9+7;
const LL Sqr=59713600;
const LL Inv=250000002;
LL n;
inline LL ksm(LL a,LL b) {LL S=1;while(b) {if(b&1) S=S*a%mod;b>>=1;a=a*a%mod;}return S;}
int main() {
	scanf("%lld",&n);
	printf("%lld\n",((ksm(1+Sqr,n)*Sqr%mod*Inv%mod-ksm(1-Sqr+mod,n)*Sqr%mod*Inv)%mod+mod)%mod);
}
posted @ 2019-03-15 08:51  asuldb  阅读(250)  评论(0编辑  收藏  举报