Codeforces 717A. Festival Organization (2900)
一个合法的串定义为:长度在 \([l,r]\) 之间,且只含 \(0,1\),并且不存在连续 \(2\) 个或更多的 \(0\)。
现在要选出 \(k\) 个长度相同的合法的串,问有几种选法,答案对 \(10^9+7\) 取模。
\(1\le k\le 200,1\le l\le r\le 10^{18}\)。
通过简单计算,可以发现答案即为 \(\sum_{i=l+2}^{r+2}\binom{F_{i}}{k}\)。
\[\begin{aligned}
\sum_{i=l+2}^{r+2}\binom{F_{i}}{k}&=\sum_{i=l+2}^{r+2}\frac{F_i^\underline{k}}{k!}\\
&=\frac{1}{k!}\sum_{i=l+2}^{r+2}\sum_{j=0}^{k}(-1)^{k-j}\begin{bmatrix}k\\j\end{bmatrix}F_i^{j}\\
&=\frac{1}{k!}\sum_{j=0}^{k}(-1)^{k-j}\begin{bmatrix}k\\j\end{bmatrix}\sum_{i=l+2}^{r+2}F_i^j
\end{aligned}
\]
第一类斯特林数可以 \(O(k^2)\) 求出,那么要计算的就是斐波那契数列 \(k\) 次方的前缀和。
考虑将通项公式 \(F_n=\frac{1}{\sqrt{5}}(\frac{1+\sqrt{5}}{2})^n-\frac{1}{\sqrt{5}}(\frac{1-\sqrt{5}}{2})^n\) 写作 \(F_{n}=ax^n-ay^n\) 代入。
\[\begin{aligned}
\sum_{i=1}^{n}F_{i}^{k}&=\sum_{i=1}^{n}(ax^i-ay^i)^k\\
&=\sum_{i=1}^{n}\sum_{j=0}^{k}(-1)^{k-j}a^k\binom{k}{j}x^{ij}y^{i(k-j)}\\
&=a^k\sum_{j=0}^{k}(-1)^{k-j}\binom{k}{j}\sum_{i=1}^{n}(x^jy^{k-j})^i\\
&=a^k\sum_{j=0}^{k}(-1)^{k-j}\binom{k}{j}\frac{[(x^jy^{k-j})^n-1]x^jy^{k-j}}{x^jy^{k-j}-1}
\end{aligned}
\]
由于 \(5\) 在模 \(10^9+7\) 意义下没有二次剩余,所以用扩域记作 \(a+b\sqrt{5}\) 的形式。注意等比数列求和中 \(x^jy^{k-j}=1\) 时特判即可。
总时间复杂度 \(O(k^2\log r)\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=305,mod=1e9+7;
struct Complex{ll x,y;};
inline ll qpow(ll a,ll b){
ll ans=1;
for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;
return ans;
}
const Complex X1={qpow(2,mod-2),qpow(2,mod-2)},X2={qpow(2,mod-2),mod-qpow(2,mod-2)};
int k;ll l,r,s[N][N],fac[N],inv[N],Inv[N];Complex ans;
inline Complex operator * (Complex x,ll y){return{x.x*y%mod,x.y*y%mod};}
inline Complex operator + (Complex x,Complex y){return{(x.x+y.x)%mod,(x.y+y.y)%mod};}
inline Complex operator - (Complex x,Complex y){return{(x.x-y.x+mod)%mod,(x.y-y.y+mod)%mod};}
inline Complex operator * (Complex x,Complex y){return{(x.x*y.x+5*x.y*y.y)%mod,(x.x*y.y+x.y*y.x)%mod};}
inline Complex operator / (Complex x,Complex y){
Complex z=y;if(z.y!=0)z.y=mod-z.y;
return x*z*qpow((y.x*y.x%mod-5*y.y*y.y%mod+mod)%mod,mod-2);
}
inline Complex cpow(Complex a,ll b){
Complex ans={1,0};
for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a;
return ans;
}
inline void precalc(int n){
fac[0]=inv[0]=Inv[0]=fac[1]=inv[1]=Inv[1]=1;
for(int i=2;i<=n;++i)
fac[i]=fac[i-1]*i%mod,
Inv[i]=(mod-mod/i)*Inv[mod%i]%mod,
inv[i]=inv[i-1]*Inv[i]%mod;
}
inline ll C(int n,int m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
inline Complex SF(ll n,int k){
Complex res={0,0};
for(int i=0;i<=k;++i){
Complex co=cpow(X1,i)*cpow(X2,k-i),oc;
if(co.x==1&&co.y==0)oc=co*n*C(k,i);
else oc=co*(cpow(co,n)-(Complex){1,0})/(co-(Complex){1,0})*C(k,i);
if((k-i)&1)res=res-oc;else res=res+oc;
}
return res;
}
int main(){
precalc(N-1);
scanf("%d%lld%lld",&k,&l,&r),l+=2,r+=2,s[0][0]=1;
for(int i=1;i<=k;++i)
for(int j=1;j<=i;++j)
s[i][j]=(s[i-1][j-1]+s[i-1][j]*(i-1))%mod;
for(int i=0;i<=k;++i){
Complex F=(SF(r,i)-SF(l-1,i))*s[k][i]*cpow({0,qpow(5,mod-2)},i);
if((k-i)&1)ans=ans-F;else ans=ans+F;
}
return printf("%lld\n",ans.x*inv[k]%mod),0;
}