CF 407C Curious Array(差分序列)

来源:互联网 发布:家用加湿器知乎 编辑:程序博客网 时间:2024/06/04 18:09

题意:给出n个数,有m个操作,每个操作是将[L,R]之间的数加上C(j-L+k,k),L<=j<=R,最后输出这n个数的值。

思路:比赛的时候拿线段树写了写,最终好像还是不太对。。。后来看群里讨论说这是差分序列什么的,就去虔诚地学了下……弄懂以后这题就不难了。首先我们知道C(x+1,k)-C(x,k)=C(x,k-1),可以发现,每次做差后k就会减1。由差分序列的性质可以知道k阶以上的差分序列全为0,可以求出在L位置的前k阶差分序列,那么就可以推出下一个数的差分序列,然后再R+1的位置减去就行了。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+1000;const int maxm=100+10;const int mod=1000000007;ll C[maxn][maxm],ans[maxn][maxm];int a[maxn];void init(){    C[0][0]=1;    for(int i=1;i<maxn;++i)    {        C[i][0]=1;        for(int j=1;j<=i&&j<maxm;++j)            C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    init();    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i)        scanf("%d",&a[i]);    int l,r,k;    while(m--)    {        scanf("%d%d%d",&l,&r,&k);        for(int i=0;i<=k;++i) ans[l][i]=(ans[l][i]+C[k][k-i])%mod;        for(int i=0;i<=k;++i) ans[r+1][i]=(ans[r+1][i]-C[k+r-l+1][k-i])%mod;    }    for(int i=1;i<n;++i)        for(int j=101;j>=1;--j)            ans[i+1][j-1]=(ans[i+1][j-1]+ans[i][j]+ans[i][j-1])%mod;    for(int i=1;i<=n;++i)        printf("%I64d ",((ans[i][0]+a[i])%mod+mod)%mod);    printf("\n");    return 0;}

0 0
原创粉丝点击