1 条题解
-
0
自动搬运
来自洛谷,原作者为

xiaoyaowudi
想回到最初原点 拨琴弦唱起岁月 不畏惧未来渺远 只牵挂那心愿搬运于
2025-08-24 22:47:18,当前版本为作者最后更新于2023-06-21 15:50:57,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
其他题解都是 的,但这题可以做到 。
第一种做法,直接容斥:
设 表示长为 ,高度为 的方案数,那么, 可以通过容斥第一个不相等的位置得到:
其中 表示斐波那契数列第 项。复杂度 ,不够优秀。
第二种做法:
另外一种理解也可以得到上述式子:设联通的生成函数是 ,那么不一定联通的生成函数是 。
注意到 的第 项是斐波那契数列的第 项的 次方,那么其应该有 次递推式。
由于斐波那契数列第 项的 次方满足:
$$\begin{aligned} F^{m}_i=&c\times \left(\phi^i-\hat{\phi}^i\right)^m\\ =&c\times \sum_{j=0}^m\binom{m}{j}\left(-1\right)^j\left(\phi^{m-j}\hat{\phi}^j\right)^i \end{aligned} $$其中 ,,。那么 的递推式有 个特征根,。
设 $P\left(x\right)=\prod_{j=0}^m\left(x-\phi^{m-j}\hat{\phi}^j\right)$,那么 ,其中 为 次多项式。
考虑如何求出 。不妨设 ,那么 $\phi^{j}\hat{\phi}^{m-j}+\phi^{m-j}\hat{\phi}^j=\left(-1\right)^j\left(\phi^{m-2j}+\hat{\phi}^{m-2j}\right)$。而 $\phi^{k}+\hat{\phi}^k=\left(\left(1+\sqrt{5}\right)/2\right)^k+\left(\left(1-\sqrt{5}\right)/2\right)^k=2^{1-k}\sum_{j\bmod 2=0}\binom{k}{j}5^{j/2}$ 是好计算的。因此将 中的项两两配对,进行 二次多项式乘法即可 得到 。
求出 后就可以 进行 乘法得到 。又 ,因此直接 递推即可得到答案。
平衡一下复杂度即为 。
代码:
#include <iostream> #include <algorithm> constexpr int N(5e5+10),p(1e9+7),_2((p+1)/2); int fp(int a,int b){int ans(1),off(a);while(b){if(b&1) ans=1ll*ans*off%p;off=1ll*off*off%p;b>>=1;}return ans;} int W(int k){return k>=p?k-p:k;} int main() { int n,m;std::cin>>n>>m; if(n<=m) { static int fib[N],f[N],g[N];fib[0]=g[0]=1; for(int i(1);i<=n;++i) { fib[i]=W(fib[i-1]+(i>1?fib[i-2]:0)); f[i]=g[i]=fp(fib[i],m); for(int j(0);j<i;++j) f[i]=(f[i]+1ll*(p-f[j])*g[i-j])%p; } std::cout<<f[n]<<std::endl; } else { static int f[N],fac[N],ifac[N],fib[N];int d(0); fac[0]=1;for(int i(1);i<N;++i) fac[i]=1ll*fac[i-1]*i%p; ifac[N-1]=fp(fac[N-1],p-2);for(int i(N-1);i;--i) ifac[i-1]=1ll*i*ifac[i]%p; if(m%2==0) { d=1;f[0]=(m%4)?1:p-1; f[1]=1; } else f[0]=1; for(int i(2-(m&1));i<=m;i+=2) { int cur(0); for(int j(0),t(fac[i]);j<=i;j+=2,t=5ll*t%p) { cur=(cur+1ll*t*ifac[j]%p*ifac[i-j])%p; } cur=1ll*cur*fp(_2,i-1)%p; int b(((m-i)%4)?cur:p-cur); static int g[N]; for(int t(0);t<=d+2;++t) { unsigned long long num((m&1)?p-f[t]:f[t]); if(t) num+=1ll*b*f[t-1]; if(t>1) num+=f[t-2]; g[t]=num%p; } d+=2; std::copy(g,g+d+1,f); } std::reverse(f,f+d+1); static int F[N],H[N]; for(int i(0);i<d;++i) { if(i<2) fib[i]=1; else fib[i]=W(fib[i-1]+fib[i-2]); F[i]=fp(fib[i],m); } for(int i(0);i<d;++i) { for(int j(0);j<=i;++j) H[i]=(H[i]+1ll*f[j]*F[i-j])%p; } int iv(fp(H[0],p-2)); for(int i(0);i<=n;++i) { int v(f[i]); for(int j(1);j<=i && j<d;++j) v=(v+1ll*(p-f[i-j])*H[j])%p; f[i]=1ll*v*iv%p; } std::cout<<(p-f[n])%p<<std::endl; } return 0; }
- 1
信息
- ID
- 8716
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者