牛客网第十场 D+差分序列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wuxiaowu547/article/details/81902442

我是题目链接
参考博客:
1 2 3
利用组合数求和规律的找法
这里写图片描述

其他的思路注释在代码后;

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int p=998244353;
const int N=2e5+10;
int n,m,T,op,l,r,w,cnt;
struct orz
{
    int x,pos,w;
} a[N];
ll fac[N],inv[N];
ll poww(ll x,int y)
{
    x%=p;
    ll ret=1;
    while (y)
    {
        if (y&1) ret=ret*x%p;
        x=x*x%p;
        y>>=1;
    }
    return ret;
}
void pre()
{
    fac[0]=1;
    for (int i=1; i<N; i++) fac[i]=fac[i-1]*i%p;
    inv[N-1]=poww(fac[N-1],p-2);
    for (int i=N-2; i>=0; i--) inv[i]=inv[i+1]*(i+1)%p;
}
ll C(int a,int b)
{
    if (b>a||b<0) return 0;
    return fac[a]*inv[b]%p*inv[a-b]%p;
}
ll solve(int x,int y)
{
    ll ret=0;
    for (int i=1; i<=cnt; i++)
    {
        if (a[i].x<=x&&a[i].pos<=y)
            ret=(ret+C(x-a[i].x+y-a[i].pos-1,x-a[i].x-1)*(ll)a[i].w%p)%p;
    }
    return ret;
}
int main()
{
    scanf("%d",&T);
    pre();
    while (T--)
    {
        scanf("%d%d",&n,&m);
        int now=1;
        cnt=0;
        while (m--)
        {
            scanf("%d",&op);
            if (op==1)
            {
                scanf("%d%d%d",&l,&r,&w);
                cnt++;
                a[cnt].x=now-1;
                a[cnt].pos=l;
                a[cnt].w=w%p;
                cnt++;
                a[cnt].x=now-1;
                a[cnt].pos=r+1;
                a[cnt].w=-w%p;
            }
            else if (op==2) now++;
            else
            {
                scanf("%d%d",&l,&r);
                ll ans=((solve(now+1,r)-solve(now+1,l-1))%p+p)%p;//now+1的意思是C(5,1)是C(1,0)+C(2,0)+C(3,0)+C(4,0)+C(5,0)的值;
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}
/*
1操作:
区间修给可以转换成单点修改,因为:
对原序列某一点进行修改,他只影响它右下侧的前缀和数组;
所以对l,r的区间修改,就相当于在(l,n)+w,在(r+1,n)-w;
各个操作1相互独立,分开来算,最后相加。
2操作:
记录下进行几次求前缀和的操作,也就是记录下操作了几次2;
为了3求和时,利用组合数求;
3操作:
我们发现在一个点+w之后,影响的是它右下角的所有点,
每个行的系数是杨辉三角的一列,所以如果在(i,j)点+w,
那么(x,y)点的系数为C(x-i+y-j-1,x-i-1)

*/

差分数组的介绍:
https://blog.csdn.net/jc514984625/article/details/53511438

有一个性质:
A[i]的差分数组是D[i], 而D[i]的前缀和sum[i]是A[i];
也就是:
A[i]: 1 2 4 5 7
D[i]: 1 1 2 1 2
sum[i]: 1 2 4 5 7

猜你喜欢

转载自blog.csdn.net/wuxiaowu547/article/details/81902442