ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P5320 [BJOI2019]勘破神机

2019-04-25 19:51:38  阅读:344  来源: 互联网

标签:BJOI2019 ch return int luogu sum binom include 勘破


传送门

首先我们要知道要求什么.显然每次放方块要放一大段不能从中间分开的部分.设\(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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有