• #4346. 御神体


    题意
    内存限制:512 MiB
    时间限制:4000 ms

    > 再往前走就是隐世了,要想回到这个世界,必须留下你最重要的东西来交换。

    小`H`来到了一个神秘的世界。在这个世界中,所有的事物都是交错的。

    要想从这个世界中逃出,小`H`需要回答 $q$ 个问题。

    对于每一个问题,都有两个值 $ n_i , m_i $,你需要计算出下面这个式子的值:

    $$sum _{i=0}^{n_i} sum _{j=0}^{m_i} inom{i}{j} [i+j equiv 0 mod 2] pmod {998244353}$$

    在这个式子中,$inom{i}{j}$ 表示从 $i$ 个物品中选出 $j$ 个物品的方案数。

    $n leq 10^6$ && $q leq 10^4$ || $n leq 10^5$ && $q leq 10^5$
    题解

    考虑杨辉三角

    对于一列,隔一个取的和,我们可以通过列方程组解出

    对于一行,隔一个取的和,可以通过上一行的前缀和得到

    设询问的答案为 $f_{n,m}$ ,若计算出了 $f_{n,m}$ ,则可以 $O(1)$ 计算出 $f_{n+1,m}$,$f_{n-1,m}$,$f_{n,m+1}$,$f_{n,m-1}$

    莫队即可

    考虑到块的大小 $L$ ,发现效率可表示为 $qL+frac{n^2}{L}$ 可得当L取 $sqrt{frac{n^2}{q}}$ 时最优秀

    代码

    #include <bits/stdc++.h>
    #define I inline
    #define _(d) while(d(isdigit(c=getchar())))
    using namespace std;char c;
    I int Rd(){int x;_(!);x=c^48;_()x=(x<<3)+(x<<1)+(c^48);return x;}
    const int N=1e6+5,P=998244353,i2=499122177;
    int Q,jc[N],ny[N],b[N],B,ans[N],s0,s1,s2,s,ax,l,r;
    struct O{int n,m,id;}q[100005];
    I int K(int x,int y){
        int A=1;
        for (;y;y>>=1,x=1ll*x*x%P)
            if (y&1) A=1ll*A*x%P;
        return A;
    }
    I int C(int x,int y){
        if (x<y || y<0) return 0;
        return 1ll*jc[x]*ny[y]%P*ny[x-y]%P;
    }
    I int X(int x){if (x>=P) x-=P;return x;}
    I bool cmp(O A,O B){
        return b[A.n]==b[B.n]?A.m<B.m:b[A.n]<b[B.n];
    }
    I void inc(){
        s=X(s+s2);if ((l+r+1)&1) s=X(s+P-C(l,r));
        s2=X(X(s2+s2)+P-C(l,r));l++;
        if (l&1) s1=X(s1+C(l,r));else s0=X(s0+C(l,r));
    }
    I void dec(){
        if (l&1) s1=X(s1-C(l,r)+P);else s0=X(s0-C(l,r)+P);
        l--;s2=1ll*X(s2+C(l,r))*i2%P;
        s=X(s-s2+P);if ((l+r+1)&1) s=X(s+C(l,r));
    }
    I void add(){
        r++;int t0=s0,t1=s1,z=C(l+1,r+1);s2=X(s2+C(l,r));
        if (l&1) s0=1ll*(z-t0+P)*i2%P,s1=1ll*(z+t0)*i2%P;
        else s0=1ll*(z+t1)*i2%P,s1=1ll*(z-t1+P)*i2%P;
        if (r&1) s=X(s+s1);else s=X(s+s0);
    }
    int main(){
        Q=Rd();for (int i=1;i<=Q;i++)
            q[i].n=Rd(),q[i].m=Rd(),q[i].id=i,
            ax=max(ax,max(q[i].n,q[i].m));
        B=(int)sqrt(1ll*ax*ax/Q)+1;
        jc[0]=1;for (int i=1;i<N;i++)
            jc[i]=1ll*i*jc[i-1]%P;
        ny[N-1]=K(jc[N-1],P-2);
        for (int i=N-1;i;i--)
            ny[i-1]=1ll*i*ny[i]%P;
        for (int i=0;i<=ax;i++) b[i]=i/B+1;
        sort(q+1,q+Q+1,cmp);
        for (int i=1;i<=Q;i++){
            if (b[q[i].n]!=b[q[i-1].n] || i<2){
                l=r=s1=0;s=s0=s2=1;
                while(l<q[i].n) inc();
                while(r<q[i].m) add();
            }
            while(l<q[i].n) inc();while(l>q[i].n) dec();
            while(r<q[i].m) add();ans[q[i].id]=s;
        }
        for (int i=1;i<=Q;i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    linux学习第一周笔记
    三授权六禁令(必背)
    内存复用三种技术
    移动平台路径相关
    unitUnity优化技巧
    游戏开发优化建议
    转载, unity 如何自定义脚本
    unity animation 在播放动画时报错 The animation state Eat could not be played because it couldn't be found!
    unity 学习之前需要做的准备
    xml 操作遇到的坑
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10684201.html
Copyright © 2020-2023  润新知