1. 程式人生 > >JZOJ5922. 【NOIP2018模擬10.23】sequence

JZOJ5922. 【NOIP2018模擬10.23】sequence

Description

小 F 是一位 Hack 國的居民,他生活在一條長度為 n 的街道上,這個街道上總共有 n 個商店。每個商店裡售賣著不同的 Hack 技能包,每個商店本身也會有個便利值。初始時,每個商店的便利值均為 0。每一天,街道上都會有一些商店優化改造。
具體來說,對於每一天,優化改造的商店都是一個連續的區間 l ∼ r,每次優化改造也會有一個優化引數 k。對於所有 l ≤ i ≤ r ,第 i 個商店的便利值會增加 C i

+ k l k C^k_{i+k-l}

小 F 想知道,m 天之後,每個商店的便利值分別是多少。由於小 F 並不喜歡高精度,因此你只需要輸出便利值對 10^9 + 7 取模的結果。

題解

可以知道,每一個加操作,都是從1開始的,
考慮用差分陣列,但是這裡這裡並不是簡單的差分,而是k階差分。
具體做法跟求C類似一階一階往上算。

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define N 500003
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
	n=0;
	ch=G();
	while((ch<'0' || ch>'9') && ch!='-')ch=G();
	int w=1;
	if(ch=='-')w=-1,ch=G();
	while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
	n*=w;
}

void write(int x){if(x>9) write(x/10);P(x%10+'0');}

const int mo=1000000007;
int s[23][N],n,m,l,r,k,c[23][N];
int add(int x,int y){return (x+y<mo?x+y:x+y-mo);}

int main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	
	read(n);read(m);
	for(int i=0;i<=n+2;i++)c[0][i]=1;
	for(int i=1;i<21;i++)
		for(int j=i;j<=n+2;j++)
			c[i][j]=add(c[i-1][j-1],c[i][j-1]);
	for(int i=1;i<=m;i++)
	{
		read(l);read(r);read(k);
		s[k][l]++;s[k][r+1]--;
		for(int j=k-1;j>=0;j--)s[j][r+1]=add(s[j][r+1],mo-c[k-j][r-l+k-j]);
	}
	for(int i=20;i+1;i--)
		for(int j=1;j<=n;j++)
			s[i][j]=add(s[i][j],add(s[i][j-1],s[i+1][j]));
	for(int i=1;i<=n;i++)
		write(s[0][i]),P('\n');
	
	return 0;
}