[BJOI2019] 勘破神机
题意:
记$F(n,k)$为用$1\times 2$的小方格填满$k$个$2\times n$的网格且每个网格的填充方案均不相同的方案数;
记$G(n,k)$为用$1\times 2$的小方格填满$k$个$3\times n$的网格且每个网格的填充方案均不相同的方案数。
给定$l,r,k$,你需要求出$ans2=\frac{1}{r-l+1}{\sum \limits_{n=l}^{r}{F(n,k)}}$或$ans3=\frac{1}{r-l+1}{\sum \limits_{n=l}^{r}{G(n,k)}}$。
$l,r\leq 10^{18},k\leq 501$。
题解:
考虑$F(n)$的递推式,发现就是斐波那契数列。
利用待定系数法解出通项$F(n)=\frac{\sqrt{5}}{5}[(\frac{1+\sqrt{5}}{2})^{n+1}-(\frac{1-\sqrt{5}}{2})^{n+1}]$。
而本题中所求$F(n,k)$实际上就是$F(n)\choose k$。
那么就可以开始推式子了,所求式为
$\sum \limits_{n=l}^{r}F(n,k)=\sum \limits_{n=l}^{r}{F(n)\choose k}=\sum \limits_{n=l}^{r}{\frac{F(n)^{\underline{k}}}{k!}}$
用第一类斯特林数将下降幂转成正常幂,得到
$=\frac{1}{k!} \sum \limits_{n=l}^{r}{\sum \limits_{i=0}^{k}{(-1)^{k-i}\begin{bmatrix} k \\ i \end{bmatrix}F(n)^{i}}}$
$=\frac{1}{k!} \sum \limits_{i=0}^{k}{(-1)^{k-i}\begin{bmatrix} k \\ i \end{bmatrix} \sum \limits_{n=l}^{r}{F(n)^{i}}}$
将右边的$F(n)$用二项式定理展开,在这里我们令$A=\frac{\sqrt{5}}{5},B=-\frac{\sqrt{5}}{5},x=\frac{1+\sqrt{5}}{2},y=\frac{1-\sqrt{5}}{2}$,则有
$=\frac{1}{k!} \sum \limits_{i=0}^{k}{(-1)^{k-i}\begin{bmatrix} k \\ i \end{bmatrix} \sum \limits_{n=l}^{r}{\sum \limits_{j=0}^{i}{{i\choose j}[(Ax)^{j}(By)^{(i-j)}]^{n+1}}}}$
$=\frac{1}{k!} \sum \limits_{i=0}^{k}{(-1)^{k-i}\begin{bmatrix} k \\ i \end{bmatrix} \sum \limits_{j=0}^{i}{{i\choose j}\sum \limits_{n=l}^{r}{[(Ax)^{j}(By)^{(i-j)}]^{n+1}}}}$
将有关$n$的项使用等比数列求和公式即可在$O(k^{2}\log{n})$的复杂度内求解。
考虑$G(n)$的递推式,发现当$n$为奇数时无解,那么我们令$G'(n)=G(2n)$。
手画一下,发现恰好填满2列时有3种方案,而填满多于2列时都只有2种方案,则有
$G'(n)=3 G'(n-1)+\sum \limits_{i=0}^{n-2}{2 G'(i)}$
$G'(n-1)=3 G'(n-2)+\sum \limits_{i=0}^{n-3}{2 G'(i)}$
用上式减下式,得到
$G'(n)-G'(n-1)=3G'(n-1)-G'(n-2)$
$G'(n)=4G'(n-1)-G'(n-2)$
将上面的$F(n)$替换成$G'(n)$再做一遍即可。
套路:
- 推式子时:注意边界条件。
- 推式子时:由不熟悉的形式转化为熟悉的形式。
代码:
#include<bits/stdc++.h> #define maxn 1005 #define maxm 500005 #define inf 0x7fffffff #define mod 998244353 #define ll long long #define rint register ll #define debug(x) cerr<<#x<<": "<<x<<endl #define fgx cerr<<"--------------"<<endl #define dgx cerr<<"=============="<<endl using namespace std; ll S[maxn][maxn],C[maxn][maxn],fac[maxn],ifac[maxn]; struct vc{ ll x,y,z; vc operator+(const vc b){vc res;res.x=(x+b.x)%mod;res.y=(y+b.y)%mod,res.z=z;return res;} vc operator-(const vc b){vc res;res.x=(x-b.x+mod)%mod;res.y=(y-b.y+mod)%mod,res.z=z;return res;} vc operator*(const vc b){vc res;res.x=(x*b.x%mod+z*y*b.y%mod)%mod;res.y=(x*b.y%mod+y*b.x%mod)%mod,res.z=z;return res;} }; inline ll read(){ ll x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } inline ll pwi(ll a,ll b){ll ans=1;while(b)ans=(b&1)?ans*a%mod:ans,a=a*a%mod,b>>=1;return ans;} inline vc mp(ll x,ll y,ll z){vc res;res.x=x,res.y=y,res.z=z;return res;} inline vc pwv(vc a,ll b){vc ans=mp(1,0,a.z);while(b)ans=(b&1)?ans*a:ans,a=a*a,b>>=1;return ans;} inline vc inv(vc a){ll iv=pwi((a.x*a.x%mod-a.z*a.y%mod*a.y%mod+mod)%mod,mod-2);return mp(a.x*iv%mod,(mod-a.y)*iv%mod,a.z);} inline void init(ll n){ S[0][0]=1;for(ll i=1;i<=n;i++)for(ll j=1;j<=i;j++)S[i][j]=(S[i-1][j-1]+(i-1)*S[i-1][j]%mod)%mod; C[0][0]=1;for(ll i=1;i<=n;i++){C[i][0]=1;for(ll j=1;j<=i;j++)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;} fac[0]=1;for(ll i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod; ifac[n]=pwi(fac[n],mod-2);for(ll i=n-1;i>=0;i--)ifac[i]=ifac[i+1]*(i+1)%mod; } int main(){ init(501); ll T=read(),m=(read()&1)?3:5; while(T--){ ll L=read(),R=read(),l=(m==5)?(L+1):(L+1)>>1,r=(m==5)?(R+1):(R>>1),k=read(),ans=0; vc A=(m==5)?mp(0,pwi(5,mod-2),m):mp(pwi(2,mod-2),pwi(6,mod-2),m),B=mp(A.x,mod-A.y,A.z); vc X=(m==5)?mp(pwi(2,mod-2),pwi(2,mod-2),m):mp(2,1,m),Y=mp(X.x,mod-X.y,X.z); for(ll i=0;i<=k;i++) for(ll j=0;j<=i;j++){ ll val=S[k][i]%mod*(((k-i)&1)?(mod-1):1)%mod*C[i][j]%mod; vc S=pwv(A,j)*pwv(B,i-j),R=pwv(X,j)*pwv(Y,i-j),iv=inv(R-mp(1,0,m)),v=(pwv(R,r+1)-pwv(R,l))*iv; ans=(R.x==1&&R.y==0)?(ans+val*S.x%mod*((r-l+1)%mod)%mod)%mod:(ans+val*((S*v).x)%mod)%mod; } printf("%lld\n",ans*pwi((R-L+1)%mod,mod-2)%mod*ifac[k]%mod); } return 0; }