(mathcal{Description})
Link.
求
[sum_{m>0\a_{1..m}>0\a_1+cdots+a_m=n}prod_{i=1}^mf_{a_i}
]
其中 (f_i) 为 Fibonacci 数列第 (i) 项((f_0=0,f_1=1)),答案对 (10^9+7) 取模。
(nle10^{10^4})。
(mathcal{Solution})
记 (F(x)) 为 ({f}) 的 OGF,首先来推导 (F(x))。根据定义 (f_{n+2}=f_{n+1}+f_n),可以发现经过适当位移,(F(x)) 能推出其自身而解出表达式。具体地:
[egin{aligned}
&~~~~~~~~~~~xF(x)+F(x)=frac{1}xF(x)-1\
&Rightarrow~~~~(x+1-frac{1}x)F(x)=-1\
&Rightarrow~~~~F(x)=frac{x}{1-x-x^2}
end{aligned}
]
令 (n) 的答案为 (g_n),(g_0=1)。简单 DP 得出递推式:
[g_n=sum_{i=1}^nf_ig_{n-i}
]
显然的卷积关系。令 ({g}) 的 OGF 为 (G(x)),则:
[egin{aligned}
G(x)&=1+G(x)F(x)\
&=frac{1}{1-F(x)}\
&=frac{1-x-x^2}{1-2x-x^2}
end{aligned}
]
提出一些常数:
[Rightarrow~~~~G(x)=1-frac{x}{x^2+2x-1}
]
我们想求 (g_n),即 ([x^n]G(x)),就得把上式最后一项分式结构配凑成等比数列求和的形式。首先暴力因式分解 (x^2+2x-1),用求根公式求出其两根:
[x_{1,2}=frac{-2pm2sqrt{2}}{2}=-1pmsqrt2
]
所以 (x^2+2x-1=(x-x_1)(x-x_2))。代入 (G(x)) 的表达式:
[egin{aligned}
G(x)&=1-frac{x}{(x-x_1)(x-x_2)}\
&=1-frac{x}{x_1-x_2}left(frac{1}{x-x_1}-frac{1}{x-x_2}
ight)\
&=1-frac{x}{x_1-x_2}left(frac{1}{x_2}sum_{i=0}^{+infty}frac{x^i}{x_2^i}-frac{1}{x_1}sum_{i=0}^{+infty}frac{x^i}{x_1^i}
ight)\
&=1-frac{1}{x_1-x_2}sum_{i=1}^{+infty}(x_2^{-i}-x_1^{-i})x^i
end{aligned}
]
拆得清清楚楚啦,答案:
[[x^n]G(x)=(x_2-x_1)^{-1}(x_2^{-n}-x_1^{-n})
]
代入 (x_{1,2}):
[[x^n]G(x)=-frac{sqrt2}4[(1-sqrt2)^n-(1+sqrt2)^n]
]
最后 (sqrt2equiv 59713600equiv 940286407pmod{10^9+7}),所以可以 (mathcal O(log p+log n))((p) 是素模数)直接算出来。
(mathcal{Code})
/* Clearink */
#include <cstdio>
const int INV4 = 250000002, S2 = 59713600, MOD = 1e9 + 7;
inline int rmod () {
int x = 0; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () );
for ( ; '0' <= s && s <= '9'; s = getchar () ) {
x = ( x * 10ll + ( s ^ '0' ) ) % ( MOD - 1 );
}
return x;
}
inline int mul ( const long long a, const int b ) { return a * b % MOD; }
inline int sub ( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline int add ( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline int mpow ( int a, int b ) {
int ret = 1;
for ( ; b; a = mul ( a, a ), b >>= 1 ) ret = mul ( ret, b & 1 ? a : 1 );
return ret;
}
int main () {
int n = rmod ();
printf ( "%d
", sub ( 0, mul ( mul ( S2, INV4 ),
sub ( mpow ( sub ( 1, S2 ), n ), mpow ( add ( 1, S2 ), n ) ) ) ) );
return 0;
}