题意:
有一个数组构成的无限矩阵,循环并斜着填总这个数组
int cursor = 0;
for (int i = 0; ; ++i) {
for (int j = 0; j <= i; ++j) {
M[j][i - j] = A[cursor];
cursor = (cursor + 1) % L;
}
}
对于i,j,我们首先要得出这个点上的数是原数组中的哪个。因为第一斜列一个数,第二斜列两个数,等差数列,所以很好求
int fin(int x,int y,int len){
return ((1+x+y)*(x+y)/2+x)%len;
}
然后我们从这个代码里发现了这样一个事情,x+2*len和y+2*len对结构是没有影响的,也就是2*len一个循环。
所以我们只要得出一个2n*2n的矩阵,就可以推出所有的位置了
代码:
#include<bits/stdc++.h>
using namespace std;
#define D long long
D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int a[100];
int M[100][100];
D fin(D x,D y,int len){
return ((1+x+y)*(x+y)/2+x)%len;
}
D su(int n){
D sum=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
sum+=M[i][j];
}
}return sum;
}
int main(){
int t;
cin>>t;
while(t--){
int n=read();
for(int i=0;i<n;i++){
a[i]=read();
}
int q=read();
while(q--){
D x,y,aa,bb;
scanf("%lld%lld%lld%lld",&x,&y,&aa,&bb);
for(D i=x;i<=x+2*n;i++){
for(D j=y;j<=y+2*n;j++){
M[i-x][j-y]=a[fin(i,j,n)];
}
}
D mull=abs(aa-x+1)/(2*n);
D mulr=abs(bb-y+1)/(2*n);
D ans=0;
ans+=su(2*n)*mull*mulr;
D l=x+2*n*mull;
D r=y+2*n*mulr;
D sul=0;D ll=aa-l+1;
for(int i=0;i<=ll-1;i++){
for(int j=0;j<2*n;j++)sul+=M[i][j];
}
ans+=mulr*sul;
D sur=0;int lr=bb-r+1;
for(int i=0;i<2*n;i++){
for(int j=0;j<=lr-1;j++)sur+=M[i][j];
}
ans+=mull*sur;
for(int i=0;i<ll;i++){
for(int j=0;j<lr;j++){
ans+=(D)M[i][j];
}
}
printf("%lld\n",ans);
}
}
}