潜龙未见静水流,沉默深藏待时秋。一朝破空声势振,惊世骇俗展雄猷。
随笔 - 80, 文章 - 0, 评论 - 3, 阅读 - 2065

ARC111F Do you like query problems? 题解

目录

题目描述

一个长为 n 的序列 a ,初始全为 0

接下来 q 次操作:

  • 1 l r v :对 lir ,令 aimin(ai,v)
  • 2 l r v :对 lir ,令 aimax(ai,v)
  • 3 l r :输出 i=lrai

其中 1lrn,0v<m

你需要统计所有 ((2m+1)n(n+1)2)q 个操作序列中,所有输出答案的和。

数据范围

  • 1n,m,q2105

时间限制 4s ,空间限制 1GB

分析

显然拆成每个位置算贡献。

T=(2m+1)n(n+1)2 ,先算期望,最后乘上 Tq 即可。

1jn ,记 fi,k 为经过 i 次操作后, aj=k 的概率, pj=j(nj+1)n(n+1)2 为区间 [l,r] 包含 j 的概率。

  • 如果 j 没有落在 [l,r] 内,显然 aj 不会变化。
  • 如果 j 落在 [l,r] 内,综合前两种操作,有 m 种操作方法可以将 aj 分别变成 0,1,,m1 ,另 m 种方法 aj 不会变化。当然,如果操作为询问, aj 也不会变化。

转移方程为:

fi,k=pj12m+1x=0m1fi1,x+(1pjm2m+1)fi1,k

初始值 f0,0=1 ,统计答案枚举询问位置:

ans=j=1ni=1qk=0m1kpj12m+1fi1,k

于是我们得到了一个O(nmq)的做法。


观察上面的转移方程,发现 k=1,2,,m1 的地位相等。

重新设计状态, fi 表示经过 i 次操作后, ai=0 的概率。则 1i<mfi=k 的概率为 1fim1

转移方程:

fi=(1pjm2m+1)fi1+pj12m+1

i 次操作对答案的贡献:

pj12m+1k=1m1k1fi1m1=pjm2(2m+1)(1fi1)

一阶线性递推,并且转移系数与 i 无关,矩阵快速幂优化:

[fi1ans1]×[1pjm2m+1pjm4m+20010pj12m+1pjm4m+21]=[fians1]

时间复杂度 O(nlogq)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+5,mod=998244353;
int m,n,q,t,res;
struct mat
{
    int v[3][3];
};
mat operator*(const mat &a,const mat &b)
{
    static mat c;
    for(int i=0;i<=2;i++)
        for(int j=0;j<=2;j++)
        {
            c.v[i][j]=0;
            for(int k=0;k<=2;k++) c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%mod;
        }
    return c;
}
int qpow(int a,int k)
{
    int res=1;
    while(k)
    {
        if(k&1) res=res*a%mod;
        a=a*a%mod,k>>=1;
    }
    return res;
}
mat qpow(mat a,int k)
{
    mat res={1,0,1,0,0,0,0,0,0};
    while(k)
    {
        if(k&1) res=res*a;
        a=a*a,k>>=1;
    }
    return res;
}
signed main()
{
    scanf("%lld%lld%lld",&n,&m,&q),t=(2*m+1)*n*(n+1)/2%mod;
    for(int j=1,tmp=m*(mod+1)/2%mod;j<=n;j++)
    {
        int p=j*(n+1-j)%mod*qpow(t,mod-2)%mod;
        mat mul={(1-p*m)%mod,-p*tmp%mod,0,0,1,0,p,p*tmp%mod,1};
        res=(res+qpow(mul,q).v[0][1])%mod;
        /**for(int i=1,x=1;i<=q;i++)
        {
            res=(res+p*tmp%mod*(1-x))%mod;
            x=((1-p*m)%mod*x+p)%mod;
        }**/
    }
    printf("%lld\n",(res+mod)*qpow(t,q)%mod);
    return 0;
}

posted on   peiwenjun  阅读(2)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示