luogu SP31428 FIBONOMIAL - Fibonacci Polynomial

背景:

偶然发现 luogu rank1 \text{luogu rank1} luogu rank1巨佬推荐这道题,就进来做做。
大水题。

题目传送门:

https://www.luogu.org/problemnew/show/SP31428

题意:

给定 n , x n,x n,x,求 D ( n , x ) = ∑ i = 1 n f i x i D(n,x)=\sum_{i=1}^{n}f_ix^i D(n,x)=i=1nfixi。其中 f f f Fibonacci \text{Fibonacci} Fibonacci序列, f 1 = 1 , f 2 = 1 , f n = f n − 1 + f n − 2 f_1=1,f_2=1,f_n=f_{n-1}+f_{n-2} f1=1,f2=1,fn=fn1+fn2

思路:

这种数据范围显然要用矩阵乘法优化或考虑通项式。
我们在生成函数——OGF证明了 Fibonacci \text{Fibonacci} Fibonacci序列的通项式为: 1 5 ( ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ) \frac{1}{\sqrt{5}}\left((\frac{1+\sqrt{5}}{2})^{n}-(\frac{1-\sqrt{5}}{2})^{n}\right) 5 1((21+5 )n(215 )n),也就是说:
D ( n , x ) = ∑ i = 1 n 1 5 ( ( 1 + 5 2 ) i − ( 1 − 5 2 ) i ) x i D(n,x)=\sum_{i=1}^{n}\frac{1}{\sqrt{5}}\left((\frac{1+\sqrt{5}}{2})^{i}-(\frac{1-\sqrt{5}}{2})^{i}\right)x^i D(n,x)=i=1n5 1((21+5 )i(215 )i)xi

D ( n , x ) = 1 5 ∑ i = 1 n ( ( 1 + 5 2 x ) i − ( 1 − 5 2 x ) i ) D(n,x)=\frac{1}{\sqrt{5}}\sum_{i=1}^{n}\left((\frac{1+\sqrt{5}}{2}x)^{i}-(\frac{1-\sqrt{5}}{2}x)^{i}\right) D(n,x)=5 1i=1n((21+5 x)i(215 x)i)

D ( n , x ) = 5 5 ( ∑ i = 1 n ( x + 5 x 2 ) i − ∑ i = 1 n ( x − 5 x 2 ) i ) D(n,x)=\frac{\sqrt{5}}{5}\left(\sum_{i=1}^{n}(\frac{x+\sqrt{5}x}{2})^{i}-\sum_{i=1}^{n}(\frac{x-\sqrt{5}x}{2})^{i}\right) D(n,x)=55 (i=1n(2x+5 x)ii=1n(2x5 x)i)

注意到两个 ∑ \sum 其实就是等比数列求和,剩下的等比数列求和即可。

如何解决 5 \sqrt{5} 5 呢?
考虑到 5 \sqrt{5} 5 m o d    ( 1 0 9 + 7 ) \mod (10^9+7) mod(109+7)下没有二次剩余,因此我们可以扩域。
简单来说就是令 z = x + y i z=x+yi z=x+yi,其中 i = 5 i=\sqrt{5} i=5 的形式。
然后类似复数的计算,有:
z 1 ± z 2 = ( x 1 + y 1 i ) ± ( x 2 + y 2 i ) = ( x 1 ± x 2 ) + ( y 1 ± y 2 ) i z1±z2=(x1+y1i)±(x2+y2i)=(x1±x2)+(y1±y2)i z1±z2=(x1+y1i)±(x2+y2i)=(x1±x2)+(y1±y2)i
z 1 ⋅ z 2 = ( x 1 + y 1 i ) ( x 2 + y 2 i ) = ( x 1 x 2 ) + ( x 1 y 2 + x 2 y 1 ) i + y 1 y 2 i 2 = ( x 1 x 2 + 5 y 1 y 2 ) + ( x 1 y 2 + x 2 y 1 ) i z1\cdot z2=(x1+y1i)(x2+y2i)=(x1x2)+(x1y2+x2y1)i+y1y2i^2=(x1x2+5y1y2)+(x1y2+x2y1)i z1z2=(x1+y1i)(x2+y2i)=(x1x2)+(x1y2+x2y1)i+y1y2i2=(x1x2+5y1y2)+(x1y2+x2y1)i
1 z = 1 x + y i = x − y i ( x + y i ) ( x − y i ) = x x 2 − 5 y 2 − y x 2 − 5 y 2 i \frac{1}{z}=\frac{1}{x+yi}=\frac{x-yi}{(x+yi)(x-yi)}=\frac{x}{x^2-5y^2}-\frac{y}{x^2-5y^2}i z1=x+yi1=(x+yi)(xyi)xyi=x25y2xx25y2yi

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define mod 1000000007
using namespace std;
struct comp
{
	LL x,y;
	comp(LL xx=0,LL yy=0):x(xx),y(yy) {}
	friend comp operator+(const comp &a,const comp &b) {return comp((a.x+b.x)%mod,(a.y+b.y)%mod);}
	friend comp operator-(const comp &a,const comp &b) {return comp((a.x-b.x+mod)%mod,(a.y-b.y+mod)%mod);}
	friend comp operator*(const comp &a,const comp &b) {return comp((a.x*b.x%mod+5ll*a.y*b.y%mod)%mod,(a.x*b.y%mod+b.x*a.y%mod)%mod);}
};
LL dg1(LL x,LL k)
{
	if(!k) return 1;
	LL op=dg1(x,k>>1);
	return (k&1)?op*op%mod*x%mod:op*op%mod;
}
LL inv1(LL x)
{
	return dg1(x,mod-2);
}
comp dg2(comp x,LL k)
{
	if(!k) return comp(1,0);
	comp op=dg2(x,k>>1);
	return (k&1)?op*op*x:op*op;
}
comp inv2(comp now)
{
	LL x=now.x,y=now.y;
	LL t=dg1((x*x%mod-5ll*y*y%mod+mod)%mod,mod-2);
    return comp(x*t%mod,(-y*t%mod+mod)%mod);
}
comp work(LL n,comp now)
{
	return (dg2(now,n+1)-now)*inv2(now-comp(1,0));
}
int main()
{
	int T;
	LL n,x;
	LL inv2=inv1(2),inv5=inv1(5);
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lld %lld",&n,&x);
		comp a=comp(inv2*x%mod,inv2*x%mod),b=comp(inv2*x%mod,(-inv2+mod)%mod*x%mod);
		printf("%lld\n",(comp(0,inv5)*(work(n,a)-work(n,b))).x);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值