多校
分块技巧
每根号n查询一次或者更新一次
#include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<algorithm> using namespace std; const int mod=1e9+7; typedef long long ll; int n,m,k,cnt; ll a[50][150005]; ll c[150005][50]; struct node { int x; ll y; }; vector<node>q; ll MOD(ll x) { return x>=mod?x%=mod:x; } void init() { int i,j; c[0][0]=1; for(i=1; i<=n; i++) { c[i][0]=1; for(j=1; j<=min(i,41); j++) { c[i][j]=c[i-1][j]+c[i-1][j-1]; c[i][j]=MOD(c[i][j]); } } for(i=1;i<41;i++) c[0][i]=1; } void update() { int x,i,j; ll y; for(i=0;i<q.size();i++) { x=q[i].x; y=q[i].y; a[0][x]+=y; } for(i=1;i<=k;i++) for(j=1;j<=n;j++) { a[i][j]=a[i-1][j]+a[i][j-1]; a[i][j]%=mod; } } ll find(int z) { int x; int i,j; ll ans=0; ll y; for(i=0;i<q.size();i++) { x=q[i].x; y=q[i].y; if(x>z) continue; ans+=c[k-1+z-x][k-1]*y; ans=ans%mod; } ans=ans+a[k][z]; return ans%mod; } int main() { int i,j,x,z; ll y; init(); scanf("%d%d%d",&n,&m,&k); memset(a,0,sizeof(a)); q.clear(); cnt=0; for(i=1; i<=m; i++) { scanf("%d",&z); if(!z) { node e; scanf("%d%lld",&x,&y); e.x=x; e.y=y; q.push_back(e); cnt++; if(cnt==800) { update(); cnt=0; } } else { scanf("%d",&x); printf("%lld\n",find(x)); } } return 0; }