题解:CF407C Curious Array
一阶差分和多维差分
一阶差分
由容斥原理
可以按维度差分,写起来更简单。
高阶差分
可以记
P4231 三步必杀
给区间
做两次差分,可以得到结论,一次操作相当于:
这样是正确的,但是操作了
一阶等差数列的二阶差分数组都为
利用这个性质,在第
具体地
可转化为
对于
这样可以避免差分系数的计算,在高阶差分有明显的好处。
CF407C Curious Array
模拟赛题,手玩发现每次加的都是一个
这是组合数的递推公式,简单展开即可证得加的序列是一个
考虑一次操作序列:
做一次差分,这里使用组合数公式展开即得:
不难发现差分一次,等差数列就降了一阶,而且多出一个尾巴。
我们采用小技巧,把这个尾巴留在当前阶差分数组,剩下的继续差分做下去。
所以一次操作等价于
:::info[code]
#include <bits/stdc++.h>
#define int long long
#define umap unordered_map
#define vint vector<int>
#define ll long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define ull unsigned long long
#define uint unsigned int
#define rg register
#define il inline
#define db double
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define sqr(x) ((x)*(x))
using namespace std;
const int INF=0x3f3f3f3f,mod=1e9+7;
const long long INFL=0x3f3f3f3f3f3f3f3f;
const double eps=1e-8;
il int read(){
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
w=(w<<1)+(w<<3)+(ch^48);
ch=getchar();
}
return w*f;
}
il void chkmax(int &x,int y){x=(x<y)?y:x;}
il void chkmin(int &x,int y){x=(x>y)?y:x;}
const int N=1e5+105,M=105;
int n,m,a[N],diff[M][N];
void add(int &x,int y){
if((x+=y)>=mod) x-=mod;
}
void sub(int &x,int y){
if((x-=y)<0) x+=mod;
}
int inv[N],frac[N];
il ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int C(int n,int m){
return 1ll*frac[n]*inv[m]%mod*inv[n-m]%mod;
}
signed main(){
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
#endif
cin>>n>>m;
frac[0]=inv[0]=1;
rep(i,1,n+100) frac[i]=1ll*frac[i-1]*i%mod;
rep(i,1,n+100) inv[i]=qpow(frac[i],mod-2);
rep(i,1,n) a[i]=read();
rep(i,1,m){
int l=read(),r=read(),k=read();
add(diff[k+1][l],1);
rep(j,1,k+1){
sub(diff[j][r+1],C(k+r-l-j+1,r-l));
}
}
per(j,101,1){
rep(i,1,n){
add(diff[j][i],diff[j][i-1]);
}
rep(i,1,n){
add(diff[j-1][i],diff[j][i]);
}
}
rep(i,1,n){
cout<<(a[i]+diff[0][i])%mod<<" ";
}
puts("");
#ifndef ONLINE_JUDGE
fprintf(stderr,"%f\n",1.0*clock()/CLOCKS_PER_SEC);
#endif
return 0;
}
::::