• [NOI2019]斗主地


    终于做出了这个把我送退役的结论题。

    由于是均匀混合,所以所有排列出现的概率相同。

    考场上我写了30分的O(mn^2)暴力,然后发现:E[ai]仍然为一次、二次函数。这个可以用期望的线性性解释。

    定义E[ai]=f(i),f(i)为关于i的一/二次函数,然后经过操作为k的变化,左边第i项变成f(i),右边第i项变成f(k+i),然后求出左边、右边(用插值)前三项即可。

    #include<bits/stdc++.h>
    typedef long long ll;
    const int mod=998244353,inv2=499122177;
    int n,m,A,Q,tp;
    int E1, E2, E3;
    ll i0,i1,i2;
    int qpow(int a,int b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod,b>>=1;
        }
        return ret;
    }
    int calc(int i)
    {
        if(i==1)return E1;
        if(i==2)return E2;
        if(i==3)return E3;
        int s1=1ll*E1*(i-2)%mod*(i-3)%mod,s2=1ll*E2*(2-2*i+mod)%mod*(i-3)%mod,s3=1ll*E3*(i-1)%mod*(i-2)%mod;
        return(1ll*s1+s2+s3)*inv2%mod;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&tp),--tp;
        i0=qpow(n,mod-2),i1=qpow(1ll*n*(n-1)%mod,mod-2),i2=qpow(1ll*n*(n-1)%mod*(n-2)%mod,mod-2);
        E1=1,E2=tp?4:2,E3=tp?9:3;
        while(m--)
        {
            scanf("%d",&A);
            ll f1=E1,f2=E2,f3=E3,f4=calc(A+1),f5=calc(A+2),f6=calc(A+3);
            E1=(f1*A+f4*(n-A))%mod*i0%mod;
            E2=(f2*A%mod*(A-1)+(f1+f4)*A%mod*(n-A)+f5*(n-A)%mod*(n-A-1))%mod*i1%mod;
            E3=(f3*A%mod*(A-1)%mod*(A-2)+(f4+2*f2)*A%mod*(A-1)%mod*(n-A)+(2*f5+f1)*A%mod*(n-A)%mod*(n-A-1)%mod+f6*(n-A)%mod*(n-A-1)%mod*(n-A-2))%mod*i2%mod;
        }
        scanf("%d",&Q);
        int X;while(Q--)scanf("%d",&X),printf("%d
    ",calc(X));
    }
    View Code
  • 相关阅读:
    C语言调试示例
    Tiff格式详解(转载)
    指纹
    twitter
    baidu
    NoSuchMethodError随记
    IllegalArgumentException异常
    Springboot2.2.9接入阿里云ES(带高亮查询)
    阿里云ECS安装cnpm
    阿里云ECS安装docker
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/13446779.html
Copyright © 2020-2023  润新知