发现询问是个等腰直角三角形,那么我们对于每条斜线作为斜边的等腰直角三角形,斜线上处理一下前缀和就可以了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
#define fi first
#define se second
using namespace std;
const int N=3005,M=3000010;
typedef unsigned int U;
typedef pair<U,int> ii;
int n,m,q;
U A,B,C;
U x,a[N][N],b[N][N],d[N][N],e[N][N];
inline unsigned int rng61(){
A ^= A << 16;
A ^= A >> 5;
A ^= A << 1;
unsigned int t = A;
A = B;
B = C;
C ^= t ^ A;
return C;
}
inline U Pow(U x,int y){
U ret=1;
for(;y;y>>=1,x=x*x) if(y&1) ret*=x;
return ret;
}
int main(){
scanf("%d%d%d%u%u%u",&n,&m,&q,&A,&B,&C);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]=x=rng61(),b[i][j]=b[i-1][j]+x,d[i][j]=d[i-1][j]+d[i][j-1]-d[i-1][j-1]+x;
U ret=0;
for(int i=1;i<=n;i++){
int x=i,y=1; U p=0;
for(int j=1;x && y<=m;j++){
p+=b[i][j]-b[x-1][j];
e[x][y]=p;
x--; y++;
}
}
//printf("%d\n",clock());
for(int i=2;i<=m;i++){
int x=n,y=i; U p=0;
for(int j=1;x && y<=m;j++){
p+=b[n][y]-b[x-1][y];
e[x][y]=p;
x--; y++;
}
}
U g=Pow(233,q-1),inv=Pow(233,2147483647);
for(int i=1;i<=q;i++){
int x=rng61()%n+1,y=rng61()%m+1,k=rng61()%min(x,y)+1;
//cout<<x<<' '<<y<<' '<<k<<endl;
U cur=e[x-k+1][y];
if(y-k>=1){
cur+=-e[x+1][y-k]-(d[x-k+1+min(n-x+k-1,y-1)][y]-d[x-k+1+min(n-x+k-1,y-1)][y-k]-d[x][y]+d[x][y-k]);
}
ret+=g*cur;
/*cout<<x-k+1+min(n-x+k-1,y-1)<<' '<<y<<endl;
cout<<x-k+1+min(n-x+k-1,y-1)<<' '<<y-k<<endl;
cout<<x<<' '<<y<<endl;
cout<<x<<' '<<y-k<<endl;*/
//c[x+1][y-k].push_back(ii(-(long long)g,y));
//c[x-k+1][y].push_back(ii(g,y));
g*=inv;
}
cout<<ret<<endl;
return 0;
}