题解 P4451 【[国家集训队]整数的lqp拆分】
jun头吉吉
·
·
题解
题意
\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_2,x_{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;
}
```