洛谷4451 整数的lqp拆分(生成函数)
比较水的一题。居然是一道没看题解就会做的黑题……
题目链接:洛谷
题目大意:定义一个长度为 $m$ 的正整数序列 $a$ 的价值为 $\prod f_{a_i}$。($f$ 是斐波那契数)对于每一个 $\sum a_i=n$ 的正整数序列,求出它们的价值之和。
$1\le n\le 10^6$。
这题一看就是生成函数瞎搞。
令 $F$ 为 $f$ 的生成函数。
那么有 $F=x\times F+x^2\times F+x$。
就有 $F=\dfrac{x}{1-x-x^2}$。
答案即为 $\sum^{\infty}_{i=0}F^i(x)[x^n]$。(注意的是不是 $F^n(x)[x^n]$,因为 $f_0=0$)
等比数列:$\dfrac{1}{1-F(x)}[x^n]$。
套进去:
$$\dfrac{1}{1-\dfrac{x}{1-x-x^2}}[x^n]$$
$$\dfrac{1-x-x^2}{(1-x-x^2)-x}[x^n]$$
$$\dfrac{1-2x-x^2+x}{1-2x-x^2}[x^n]$$
$$(1+\dfrac{x}{1-2x-x^2})[x^n]$$
$$\dfrac{x}{1-2x-x^2}[x^n]$$
这个生成函数似乎与 $F$ 长得有点像……令它为 $G$,是数列 $g$ 的生成函数。要求即为 $g[n]$。
$(1-2x-x^2)G=x$
$G=2x\times G+x^2\times G+x$
那么就有 $g[0]=0,g[1]=1,g[i]=2g[i-1]+g[i-2](i\ge 2)$。
此时可以用矩阵快速幂做到 $O(\log n)$。但是这么小的 $n$……
时间复杂度 $O(n)$。

#include<bits/stdc++.h> using namespace std; const int maxn=1000100,mod=1000000007; #define FOR(i,a,b) for(int i=(a);i<=(b);i++) #define ROF(i,a,b) for(int i=(a);i>=(b);i--) #define MEM(x,v) memset(x,v,sizeof(x)) inline int read(){ int x=0,f=0;char ch=getchar(); while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return f?-x:x; } int n,g[maxn]; int main(){ n=read(); g[0]=0;g[1]=1; FOR(i,2,n) g[i]=(2ll*g[i-1]+g[i-2])%mod; printf("%d\n",g[n]); }