• CF407C.Curious Array k阶差分


    CF407C.Curious Array k阶差分

    题意

    给定长度为(n)的数组(a),进行(m)次修改,每次修改给定(l ,r,k),给区间([l,r])加上(inom{j - l_i + k_i}{k_i})

    求所有修改以后每个数的值

    [1 leq n,mleq10^5\ 0leq a_i leq 10^9\ 1leq l_i leq r_i leq n,0leq k leq 100 ]

    分析

    尝试从(k)比较小来入手,显然给定的(a)初始大小我们并不关心

    考虑(a)数组的差分数组

    1阶差分

    [inom{k-1}{k-1},inom{k}{1}...inom{r-l+k-1}{k-1}\ ]

    二阶差分

    [inom{k-2}{k-2},inom{k-1}{k-2}...inom{r-l+k-2}{k-2} ]

    (n)阶差分

    [inom{k-n}{k-n},inom{k-n+1}{k-n}...inom{k-l+k-n}{k-n} ]

    如果能够维护(n)阶差分数组,就可以最后对差分数组做前缀和还原出原数组,容易发现最多进行(k+1)次差分后全部变为0,再注意维护r+1$的位置

    他们的和就是(sum_{i=0}^kinom{r-l+k-i}{r-l} = inom{r-l+k-i+1}{k-i+1})

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<ll,int>
    using namespace std;
    typedef long long ll;
    typedef vector<int> VI;
    
    inline ll rd(){
        ll x;
        scanf("%lld",&x);
        return x;
    }
    
    const int MOD = (int)1e9 + 7;
    
    inline void add(int &a,int b){
        a += b;
        if(a >= MOD) a -= MOD;
    }
    
    inline int mul(int a,int b){
        return (ll)a * b % MOD;
    }
    
    inline int ksm(int a,int b = MOD - 2,int m = MOD){
        int ans = 1;
        int base = a;
        while(b){
            if(b & 1) ans = mul(ans,base);
            base = mul(base,base);
            b >>= 1;
        }
        return ans;
    }
    
    
    const int maxn = 2e5 + 5;
    
    int iv[maxn];
    int fac[maxn];
    
    inline int C(int n,int m){
        if(n < m) return 0;
        return mul(fac[n],mul(iv[m],iv[n - m]));
    }
    
    int ans[maxn][105];
    int a[maxn];
    
    int main(){
        fac[0] = iv[0] = 1;
        for(int i = 1;i < maxn;i++)
            fac[i] = mul(fac[i - 1],i);
        iv[maxn - 1] = ksm(fac[maxn - 1]);
        for(int i = maxn - 2;i;i--)
            iv[i] = mul(iv[i + 1],i + 1);
        int n = rd();
        int m = rd();
        for(int i = 1;i <= n;i++)
            a[i] = rd();
        for(int i = 0;i < m;i++){
            int l = rd();
            int r = rd();
            int k = rd();
            for(int j = 0;j <= k;j++){
                add(ans[l][j],C(k,k - j));
            }
            for(int j = 0;j <= k;j++){
                add(ans[r + 1][j],MOD - C(r - l + k + 1,k - j));
            }
        }
        for(int i = 1;i < n;i++)
            for(int j = 101;j >= 1;j--)
                add(ans[i + 1][j - 1],(ans[i][j] + ans[i][j - 1]) % MOD);
        for(int i = 1;i <= n;i++)
            printf("%d ",(ans[i][0] + a[i]) % MOD);
    }
    
  • 相关阅读:
    System V 消息队列
    《APUE》读书笔记第十五章进程间通信
    感冒休息
    《APUE》读书笔记—第十一章线程
    消息队列和管道的区别(转载)
    《APUE》读书笔记第十八章终端I/O
    《APUE》读书笔记第十九章伪终端
    《APUE》读书笔记第十六章网络IPC:套接字
    [转]阿里要走102年,阿里的工程师能走多远呢?
    Posix消息队列
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15484659.html
Copyright © 2020-2023  润新知