JZOJ5922. 【NOIP2018模拟10.23】sequence

传送门

preface  

  这道题想了好久好久主要是菜,但其实并不是很难,大佬现在走还来得及。。。。

分析

  这道题乍一看没什么想法,暴力50pts骗走溜掉。但其实那个特殊点提示很大。

  对于第5个点的话,把式子化简出来就是i-l+1,i-l+2...就这个点而言,就可以开两个差分数组f,g,分别表示第i个位置的一次项系数和常数的差分。更新就变成了O(1)的。

  再把差分扩展到20,也不过是个二十一阶差分嘛。然后,对于每i阶的差分来说,都要做i次才能得到真正的值,而多次差分的数列正好对应帕斯卡矩阵的r-l+1行/列,也就是杨辉三角的r-l+1列,也就是一个组合数。所以对于每个修改,在l的对应阶的差分数组上++,r+1的--,然后在r+1处向低阶减k个组合数从而保证其他阶不变。

  最后更新答案时一定要从高阶往低阶更新,这样才能保证每i阶都差分了i次,注意逆元和月莫就可以了。

p.s.我用预处理帕斯卡矩阵挂了后三个点??如果你用帕斯卡矩阵过了的话请留个评论。

code

 

#include<bits/stdc++.h>
#define ll long long
#define maxn 500010
#define reg register
#define mod 1000000007
using namespace std;
inline void read(int &x)
{
    x=0;
    reg char s=getchar();
    while(s<'0' || s>'9') s=getchar();
    while(s>='0' && s<='9') x=x*10+s-'0',s=getchar();
}
inline void print(ll x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9) print(x/10ll);
    putchar(x%10ll+'0');
}
int n,m;
ll a[maxn][25],b[maxn][25],inv[maxn];
void pre()
{
    inv[1]=1;
    for(int i=2; i<=n; i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
int main()
{
    read(n),read(m);
    pre();
    reg int l,r,k;
    for(reg int i=1; i<=m; i++)
    {
        read(l),read(r),read(k);
        a[l][k]=(a[l][k]+1)%mod;
        ll tmp=1,t=r-l;
        for(reg int j=k; ~j; j--)
        {
            a[r+1][j]=(a[r+1][j]-tmp+mod)%mod;
            t++;
            tmp=tmp*t%mod*inv[t-(r-l)]%mod;
        }
    }
    for(reg int i=20; ~i; i--)
        for(reg int j=1; j<=n; j++)
            b[j][i]=((a[j][i]+b[j][i+1])%mod+b[j-1][i])%mod;
    for(reg int i=1; i<=n; i++) print(b[i][0]),putchar('\n');
    return 0;
}

转载于:https://www.cnblogs.com/wCTSd/p/9846285.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值