zoukankan      html  css  js  c++  java
  • [BJOI2019] 勘破神机

    题意:

    记$F(n,k)$为用$1 imes 2$的小方格填满$k$个$2 imes n$的网格且每个网格的填充方案均不相同的方案数;

    记$G(n,k)$为用$1 imes 2$的小方格填满$k$个$3 imes 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,rleq 10^{18},kleq 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}egin{bmatrix} k \ i end{bmatrix}F(n)^{i}}}$

    $=frac{1}{k!} sum limits_{i=0}^{k}{(-1)^{k-i}egin{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}egin{bmatrix} k \ i end{bmatrix} sum limits_{n=l}^{r}{sum limits_{j=0}^{i}{{ichoose j}[(Ax)^{j}(By)^{(i-j)}]^{n+1}}}}$

    $=frac{1}{k!} sum limits_{i=0}^{k}{(-1)^{k-i}egin{bmatrix} k \ i end{bmatrix} sum limits_{j=0}^{i}{{ichoose 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
    ",ans*pwi((R-L+1)%mod,mod-2)%mod*ifac[k]%mod);
        }
        return 0;
    }
    勘破神机
  • 相关阅读:
    中断
    按键
    uart stdio的移植1
    串口通信实战
    串口通信相关知识详解
    SOC时钟
    arm-linux-ld: cannot find sdram_init.o
    SDRAM初始化
    代码重定位实战
    s5pv210的启动过程
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13138941.html
Copyright © 2011-2022 走看看