题解 P4451 【[国家集训队]整数的lqp拆分】

· · 题解

题意

\large{\sum_{\small\sum_{i=1}^ma_i=n,a_i>0}}\small\prod_{i=1}^m F_{a_i}

题解

小清新生成函数。

记斐波那契数列的第i项为fib_i,那么有:fib_0=0,fib_1=1,fib_n=fib_{n-1}+fib_{n-2}

F(x)=\sum_{i=0}^{+\infty}fib_ix^i,即斐波那契的生成函数,那么显然有:

\begin{alignedat}{2} F(x)&=fib_0+&fib_1\times x+&fib_2\times x^2+fib_3\times x^3+fib_4\times x^4+\ldots(1)\\ xF(x)&=&fib_0\times x+&fib_1\times x^2+fib_2\times x^3+fib_3\times x^4+\ldots(2)\\ x^2F(x)&=&&fib_0\times x^2+fib_1\times x^3+fib_2\times x^4+\ldots(3)\\ \end{alignedat} $$(x+x^2)F(x)=fib_2\times x^2+fib_3\times x^3+fib_4\times x^4\ldots$$ 与$(1)$式对比一下,有: $$F(x)=(x+x^2)F(x)+x$$ $$F(x)=\frac{x}{1-x-x^2}$$ 设$n$的答案为$g_n$,递推式应该比较容易。就是枚举最后的一个数字,在原来的基础上乘上这个数的斐波那契值,在累加答案,最后的式子应该就是: $$g_n=\sum_{i=1}^ng_ifib_{n-i}$$ 特别地,我们令$g_0=1 g_n=[n=0]+\sum_{i=1}^ng_ifib_{n-i}

g的生成函数为G,即G(x)=\sum_{i=0}^{+\infty}g_ix^i,那么对其进行展开:

G(x)=\sum_{n=0}^{+\infty}([n=0]+\sum_{i=1}^ng_ifib_{n-i})x^n G(x)=1+\sum_{n=1}^{+\infty}(\sum_{i=1}^ng_ifib_{n-i})x^n

不难发现,\sum_{n=1}^{+\infty}(\sum_{i=1}^ng_ifib_{n-i})x^n=F(x)\times G(x),因此:

G(x)=1+F(x)\times G(x) G(x)=\frac{1}{1-F(x)}=\frac{1}{1-\frac{1}{1-x-x^2}} =\frac{1-x-x^2}{1-2x-x^2}=1-\frac{x}{x^2+2x-1}

此时只需要展开-\frac{x}{x^2+2x-1}即可。

我们知道,\frac{1}{1-cx^k}=\sum_{i=0}^{+\infty}(cx)^{ik},因此我们希望上式可以用这样的方式展开。

我们只需要解出x^2+2x-1=0的两根x_1,x_2x_{1,2}=-1±\sqrt{2},那么就有:

-\frac{x}{x^2+2x-1}=-\frac{x}{(x-x_1)(x-x_2)} =\frac{x}{x_2-x_1}(\frac{1}{x-x_1}-\frac{1}{x-x_2})

把常数项化为1

=\frac{x}{x_2-x_1}(\frac{1}{x2}\times\frac{1}{1-x/x2}-\frac{1}{x1}\times\frac{1}{1-x/x1}) =\frac{x}{x_2-x_1}(\frac{1}{x2}\times\sum_{i=0}\frac{x^i}{x_2^i}-\frac{1}{x1}\times\sum_{i=0}\frac{x^i}{x_1^i}) =\frac{1}{x_2-x_1}(\sum_{i=0}\frac{x^{i+1}}{x_2^{i+1}}-\sum_{i=0}\frac{x^{i+1}}{x_1^{i+1}})

那么第n项的系数为g(n)=\dfrac{1}{x2-x1}\times(\dfrac{1}{x_2^n}-\dfrac{1}{x_1^n})

代入得到:g(n)=\dfrac{\sqrt{2}}{4}[(1+\sqrt{2})^n-(1-\sqrt{2})^n]

但是由于$n$的值很大,根据费马小定理,对$mod-1$取模即可。 ## 代码 ```cpp #include<bits/stdc++.h> using namespace std; typedef long long ll; template<const int mod> struct modint{ ll x; modint(ll o=0){x=o;} modint &operator = (ll o){return x=o,*this;} modint &operator +=(modint o){return x=x+o.x>=mod?x+o.x-mod:x+o.x,*this;} modint &operator -=(modint o){return x=x-o.x<0?x-o.x+mod:x-o.x,*this;} modint &operator *=(modint o){return x=1ll*x*o.x%mod,*this;} modint &operator ^=(ll b){ b%=(mod-1); modint a=*this,c=1; for(;b;b>>=1,a*=a)if(b&1)c*=a; return x=c.x,*this; } modint &operator /=(modint o){return *this *=o^=mod-2;} modint &operator +=(ll o){return x=x+o>=mod?x+o-mod:x+o,*this;} modint &operator -=(ll o){return x=x-o<0?x-o+mod:x-o,*this;} modint &operator *=(ll o){return x=1ll*x*o%mod,*this;} modint &operator /=(ll o){return *this *= ((modint(o))^=mod-2);} template<class I>friend modint operator +(modint a,I b){return a+=b;} template<class I>friend modint operator -(modint a,I b){return a-=b;} template<class I>friend modint operator *(modint a,I b){return a*=b;} template<class I>friend modint operator /(modint a,I b){return a/=b;} friend modint operator ^(modint a,ll b){return a^=b;} friend bool operator ==(modint a,ll b){return a.x==b;} friend bool operator !=(modint a,ll b){return a.x!=b;} bool operator ! () {return !x;} modint operator - () {return x?mod-x:0;} void read(){ string s;cin>>s;x=0; for(int i=0;i<s.length();i++) *this*=10,*this+=s[i]-'0'; }void write(){ cout<<x; } }; modint<1000000006>n; modint<1000000007>ans,sqrt2=59713600; signed main(){ n.read(); ans=sqrt2/4*(((sqrt2+1)^n.x)-((-sqrt2+1)^n.x));ans.write(); return 0; } ```