zoukankan      html  css  js  c++  java
  • [BJOI2019]勘破神机(斯特林数+二项式定理+数学)

    题意:f[i],g[i]分别表示用1*2的骨牌铺2*n和3*n网格的方案数,求ΣC(f(i),k)和ΣC(g(i),k),对998244353取模,其中l<=i<=r,1<=l<=r<=1e18

    题解:显然打表发现f[i]为斐波那契数列,g[2i+1]=0,g[2i]=4g[2i-2]-g[2i-4]。

    然后考虑m=2的斐波那契部分:k是给定的,仅需求斐波那契数列的下降幂,然后可以用第一类斯特林数去转换,然后求斐波那契数列的幂之和,假设斐波那契数列的两个特征根为a,b,则f(n,k)=(An-Bn)k/(√5)k,然后可以用二项式定理展开,但模数太差是998244353,所以要扩域。其实这道题是一道原题,原题链接:CF717A

    m=3,因为也是二阶递推式,所以解法是一样的。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=600,mod=998244353;
    int c[N][N],s[N][N];
    int qpow(int a,ll b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod,b>>=1;
        }
        return ret;
    }
    struct num{
        int a,b,c;
        num operator+(num x){return (num){(a+x.a)%mod,(b+x.b)%mod,c};}
        num operator-(num x){return (num){(a-x.a+mod)%mod,(b-x.b+mod)%mod,c};}
        num operator*(num x)
        {return (num){(1ll*a*x.a+1ll*c*b%mod*x.b)%mod,(1ll*a*x.b+1ll*b*x.a)%mod,c};}
        num inv()
        {
            int f=qpow((1ll*a*a-1ll*b*b%mod*c%mod+mod)%mod,mod-2);
            return (num){1ll*a*f%mod,1ll*(mod-b)*f%mod,c};
        }
        bool operator==(num x){return a==x.a&&b==x.b&&c==x.c;}
        num operator/(num x){return (*this)*x.inv();}
    };
    num qpow(num a,ll b)
    {
        num ret=(num){1,0,a.c};
        while(b)
        {
            if(b&1)ret=ret*a;
            a=a*a,b>>=1;
        }
        return ret;
    }
    int F(ll n,int k)
    {
        if(!k)return n%mod;
        n++;
        num ans=(num){0,0,5},A=(num){1,1,5}/(num){2,0,5},B=(num){1,mod-1,5}/(num){2,0,5};
        num x=(num){1,0,5},y=(num){1,0,5};
        for(int j=1;j<=k;j++)y=y*B;
        for(int j=0;j<=k;j++)
        {
            int ret=c[k][j];
            if(k-j&1)ret=(mod-ret)%mod;
            num t=x*y;
            if(t==(num){1,0,5})ans=ans+(num){n%mod*ret%mod,0,5};
            else ans=ans+(num){ret,0,5}*(qpow(t,n+1)-t)/(t-(num){1,0,5});
            x=x*A,y=y/B;
        }
        for(int j=1;j<=k;j++)ans=ans/(num){0,1,5};
        return (ans.a+mod-1)%mod;
    }
    int calf(ll n,int k)
    {
        if(!n)return 0;
        int ret=0,sum;
        for(int j=0;j<=k;j++)
        sum=1ll*F(n,j)*s[k][j]%mod,ret=(k-j&1)?(ret-sum+mod)%mod:(ret+sum)%mod;
        for(int i=1;i<=k;i++)ret=1ll*ret*qpow(i,mod-2)%mod;
        return ret;
    }
    int G(ll n,int k)
    {
        if(!k)return n%mod;
        num ans=(num){0,0,3},x1=(num){2,1,3},x2=(num){2,mod-1,3};
        num A=(num){3,1,3},B=(num){3,mod-1,3},x=(num){1,0,3},y=x,a=x,b=x;
        for(int j=1;j<=k;j++)y=y*x2,b=b*B;
        for(int j=0;j<=k;j++)
        {
            int ret=c[k][j];
            num t=x*y;
            if(t==(num){1,0,3})ans=ans+a*b*(num){n%mod*ret%mod,0,3};
            else ans=ans+(num){ret,0,3}*a*b*(qpow(t,n+1)-t)/(t-(num){1,0,3});
            x=x*x1,y=y/x2,a=a*A;b=b/B;
        }
        for(int j=1;j<=k;j++)ans=ans/(num){6,0,3};
        return ans.a;
    }
    int calg(ll n,int k)
    {
        if(!n)return 0;
        n/=2;
        int ret=0,sum;
        for(int j=0;j<=k;j++)
        sum=1ll*G(n,j)*s[k][j]%mod,ret=(k-j&1)?(ret-sum+mod)%mod:(ret+sum)%mod;
        for(int i=1;i<=k;i++)ret=1ll*ret*qpow(i,mod-2)%mod;
        return ret;
    }
    int main()
    {
        for(int i=0;i<=590;i++)
        {
            c[i][0]=1;
            for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod; 
        }
        s[0][0]=1;
        for(int i=1;i<=590;i++)
        for(int j=1;j<=i;j++)
        s[i][j]=(s[i-1][j-1]+1ll*(i-1)*s[i-1][j])%mod;
        int T,m;scanf("%d%d",&T,&m);
        while(T--)
        {
            ll l,r;int k;cin>>l>>r>>k;
            int ans=m==2?(calf(r,k)-calf(l-1,k)+mod)%mod:(calg(r,k)-calg(l-1,k)+mod)%mod;
            ans=1ll*ans*qpow((r-l+1)%mod,mod-2)%mod;
            printf("%d
    ",ans);
        }
    }
    View Code
  • 相关阅读:
    打开安装 好的Microsoft Dynamics CRM 4.0 报错误为 Caller does not have enough privilege to set CallerOriginToken to the specified value 的解决办法
    基于 Windows Server 2008 的计算机对 Microsoft Dynamics CRM 4.0 的支持
    Microsoft Dynamics CRM 4.0 如何添加自定义按钮
    Microsoft Dynamics CRM 4.0 Plugin 取值,赋值,查询
    C# 中的 enum(枚举) 类型使用例子
    vue事件的绑定
    表单验证2
    node中模块
    node模块的引入
    node中的读文件
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10746324.html
Copyright © 2011-2022 走看看