2019.03.29【洛谷P4451】【BZOJ2173】整数的lqp拆分(生成函数)
程序员文章站
2022-05-08 19:06:02
...
洛谷传送门
BZOJ传送门
解析:
设表示一个整数的lqp拆分的权值,其生成函数为,表示第个斐波那契数,生成函数为。
令
很显然我们可以发现:
也就是
我们知道斐波那契数列的生成函数闭形式是,代到上面去可以得到。
也就是,最后面那个是对于的,不用管,对于,我们得到递推式。
推到这里已经可以过这道题了,那么我们把放到如何?
显然我们继续推是可以得到通项公式的。
拆掉分母:
待定系数,设
恒等变形解得
随手写一个二次剩余,或者直接暴力,也不慢,内随便跑出来,我们得到
通项公式:
代码:(递推)
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
cs int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
int n;
int g[1000006];
signed main(){
std::cin>>n;
g[1]=1;
for(int re i=2;i<=n;++i)g[i]=add(add(g[i-1],g[i-1]),g[i-2]);
std::cout<<g[n]<<"\n";
return 0;
}
代码:(通项)
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
cs int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int quickpow(int a,int b,int res=1){
while(b){
if(b&1)res=mul(res,a);
a=mul(a,a);
b>>=1;
}
return res;
}
cs int sqr2=59713600,inv2=(mod+1)>>1;
int n;
signed main(){
std::cin>>n;
std::cout<<mul(mul(sqr2,mul(inv2,inv2)),dec(quickpow(add(1,sqr2),n),quickpow(dec(1,sqr2),n)));
return 0;
}