差分、前缀和和组合数

差分、前缀和和组合数

1、

所加的如果式组合数的话,可以通过多次前缀和求得,进而用差分解决区间加的问题。

# include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN=1e5+100;
const LL mod=1e9+7;

LL a[MAXN],c[MAXN][105],f[MAXN][105];
void init()
{
   for(int i=0;i<MAXN;++i) c[i][0]=1;
   for(int i=1;i<MAXN;++i){
       for(int j=1;j<105;++j){
           c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
      }
  }
   return ;
}
int main()
{
   init();
   int N,M; scanf("%d%d",&N,&M);
   for(int i=1;i<=N;++i){
       scanf("%lld",&a[i]);
  }
   int L,R,K;
   for(int i=1;i<=M;++i){
       scanf("%d%d%d",&L,&R,&K);
       f[L][K]=(f[L][K]+1)%mod;
       for(int j=K;j>=0;j--){
           f[R+1][j]=(f[R+1][j]-c[K-j+R-L][K-j]);
      }
  }
   for(int i=100;i>=0;i--){
       for(int j=1;j<=N;++j){
           f[j][i]=(f[j][i]+f[j-1][i])%mod;
           f[j][i]=(f[j][i]+f[j][i+1])%mod;
      }
  }
   for(int i=1;i<=N;++i){
       printf("%lld ",((f[i][0]+a[i])%mod+mod)%mod);
  }
   printf("\n");
   return 0;
}

2、[L,n]区间分别加上1,x,x^2

1)常数:直接差分

2) x=1,2,3

x:二次前缀和

void get(int *a,int n){
for(int i = 1;i <= n;i++){
a[i] += a[i-1];
}
}
int main(){
for(int i = 1;i <= m;i++){
cin >> pos;
a[pos]++;
}
get(a);//第一次让每个值都加上1
get(a);//第二次让每个值加上与L的距离
return 0;
}

ax+b:

void get(int *a,int n){
   for(int i = 1;i <= n;i++){
      a[i] += a[i-1];
  }
}
int POS[MAN];
int main(){
  int cnt = 0;
  for(int i = 1;i <= m;i++){
      cin >> pos;
      POS[cnt++] = pos;
      a[pos] += A;//假设A已给出
  }
   get(a);//第一次让每个值都加上A
   for(int i = 0;i < cnt;i++){
   a[POS[i]]+= B;//假设B已给出
  }
   get(a);//第二次让每个值加上与L的距离
   return 0;
}

3) x^2= 1^2、2^2、3^2

void get(int *a,int n){
   for(int i = 1;i <= n;i++){
      a[i] += a[i-1];
  }
}
int main(){
for(int i = 1;i < =m;i++){
int pos;cin >>pos;
a[pos]++;//当前位置加一很容易理解。
a[pos+1]++;//这里可能会比较难懂,pos+1这个位置加上1,就是pos对于n的相对位置是x,而pos+1对于n的相对位置就是x-1
}
get(a,n);
get(a,n);//前2个就是得到x。
get(a,n);//对x进行求前缀和,得到sn.
return 0;
}

3.

k次多项式的k+1阶差分可以用k+1个常数来表示,并且这k+1个常数的和总是等于最高项系数乘以k的阶乘。

posted @ 2022-02-26 23:20  fengzlj  阅读(183)  评论(0)    收藏  举报