其他分享
首页 > 其他分享> > luogu P5320 [BJOI2019]勘破神机

luogu P5320 [BJOI2019]勘破神机

作者:互联网

传送门

首先我们要知道要求什么.显然每次放方块要放一大段不能从中间分开的部分.设\(m=2\)方案为\(f\),\(m=3\)方案为\(g\),\(m=2\)可以放一个竖的,或者两个横的,所以\(f_i=f_{i-1}+f_{i-2}\);\(m=3\),因为只有\(i\)为偶数有值,所以后面的\(i\)其实是\(2i\),然后可以发现要么放三个横的,要么像下面这样放长度为偶数的块

|--|   ------
|--|   |----|
----   |----|

可以注意到每种长度都有两种方案(长度为\(2\)因为有三个横的所以是三种),所以\(g_i=3g_{i-1}+\sum_{j=2}^{i}2g_{i-j}\),打表可以发现其实是\(g_i=4g_{i-1}-g_{i-2}(g_1=3)\).因为要从某种长度中选\(k\)个,所以要求\((m=2)\sum_{i=l}^r \binom{f_i}{k}\).显然只要考虑\([1,r]\)和\([1,l-1]\)的值

\(k\)较小,我们可以把组合数看成一个\(k+1\)次项的多项式\(\binom{n}{k}=\frac{1}{k!}\prod_{i=0}^{k}(n-i)\),后面记第\(i\)项系数为\(s_i\),那么我们要求的是\[\sum_{i=1}^n \sum_{j=0}^{k} a_j{f_i}^j\]\[ \sum_{j=0}^{k} a_j\sum_{i=1}^n{f_i}^j\]

后面那个东西不大好求,考虑我们已经知道递推式了,可以利用特征方程解出通项公式,可以去这里学,所以\(f\)的通项公式是自己去网上找,然后稍微改一下,\(g\)的公式是\(g_n=\frac{3-\sqrt{3}}{6}(2+\sqrt{3})^n+\frac{3+\sqrt{3}}{6}(2-\sqrt{3})^n\),后面为了方便,统一记为\(ab^n+cd^n\)

然后继续推式子\[ \sum_{j=0}^{k} a_j\sum_{i=1}^n(ab^i+cd^i)^j\]

二项式定理展开\[ \sum_{j=0}^{k} a_j\sum_{i=1}^n\sum_{l=0}^{j}\binom{j}{l} (ab^i)^l(cd^i)^{j-l}\]\[ \sum_{j=0}^{k} a_j\sum_{l=0}^{j}\binom{j}{l}\sum_{i=1}^n a^lb^ilc^{j-l}d^{i(j-l)}\]\[ \sum_{j=0}^{k} a_j\sum_{l=0}^{j}\binom{j}{l}a^lc^{j-l}\sum_{i=1}^n (b^ld^{j-l})^i\]

后面可以等比数列求和,然后直接做就行了

注意\(3\)和\(5\)在模\(998244353\)意义下没有二次剩余,所以把运算的数记为\(a+b\sqrt{c}\),然后写个类型,定义一下运算就好了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double

using namespace std;
const int N=1000+20,mod=998244353;
LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
int inv(int a){return fpow(a,mod-2);}
int kk,s[N],fac[N],iac[N],bs;
int C(int n,int m){return m<0||n<m?0:1ll*fac[n]*iac[m]%mod*iac[n-m]%mod;}
struct node
{
    int a,b;
    node(){a=b=0;}
    node(int na,int nb){a=na,b=nb;}
    node operator + (const node &bb) const {return node((a+bb.a)%mod,(b+bb.b)%mod);}
    node operator - (const node &bb) const {return node((a-bb.a+mod)%mod,(b-bb.b+mod)%mod);}
    node operator * (const node &bb) const {return node((1ll*a*bb.a+1ll*b*bb.b%mod*bs)%mod,(1ll*a*bb.b+1ll*b*bb.a)%mod);}
    node operator * (const LL &bb) const {return node(1ll*a*bb%mod,1ll*b*bb%mod);}
    node invv(){int dt=inv((1ll*a*a-1ll*bs*b*b%mod+mod)%mod);return node(1ll*a*dt%mod,(mod-1ll*b*dt%mod)%mod);}
    node operator ^ (const LL &bb) const
    {
        node an,a=*this;
        an.a=1;
        LL bbb=bb;
        while(bbb)
        {
            if(bbb&1) an=an*a;
            a=a*a,bbb>>=1;
        }
        return an;
    }
}a,b,c,d,yi;
node dbsl(node aa,LL n){return aa.a==1&&aa.b==0?node(n%mod,0):(yi-(aa^n))*((yi-aa).invv());}
int sov(LL n)
{
    int an=0;
    for(int j=0;j<=kk;++j)
    {
        node sm;
        for(int l=0;l<=j;++l)
            sm=sm+(a^l)*(c^(j-l))*(dbsl((b^l)*(d^(j-l)),n+1)-yi)*C(j,l);
        an=(an+1ll*s[j]*sm.a%mod)%mod;
    }
    return 1ll*an*iac[kk]%mod;
}

int main()
{
    yi.a=1;
    fac[0]=1;
    for(int i=1;i<=N-10;++i) fac[i]=1ll*fac[i-1]*i%mod;
    iac[N-10]=inv(fac[N-10]);
    for(int i=N-10;i;--i) iac[i-1]=1ll*iac[i]*i%mod;
    int T=rd(),op=rd();
    if(op==2)
    {
        bs=5;
        a=node(inv(2),inv(10)),b=node(inv(2),inv(2)),c=node(inv(2),mod-inv(10)),d=node(inv(2),mod-inv(2));
    }
    else
    {
        bs=3;
        a=node(inv(2),mod-inv(6)),b=node(2,1),c=node(inv(2),inv(6)),d=node(2,mod-1);
    }
    while(T--)
    {
        LL l=rd(),r=rd(),ln=(r-l+1)%mod;kk=rd();
        if(op==3) l=(l+1)/2+1,r=r/2+1;
        memset(s,0,sizeof(int)*(kk+3));
        s[0]=1;
        for(int i=0;i<kk;++i)
        {
            for(int j=kk;j;--j) s[j]=(1ll*s[j]*(mod-i)%mod+s[j-1])%mod;
            s[0]=1ll*s[0]*(mod-i)%mod;
        }
        printf("%lld\n",1ll*(sov(r)-sov(l-1)+mod)%mod*inv(ln)%mod);
    }
    return 0;
}

标签:BJOI2019,ch,return,int,luogu,sum,binom,include,勘破
来源: https://www.cnblogs.com/smyjr/p/10770506.html