题解思路:首先最最重要的就是要注意到1e7这个数很暧昧,它非常小,因此两个整数的平方和 <= 1e7 的情况是十分有限的,我们可以先预处理1——1e7 = 另外两个数平方和 的情况,之后在m次询问中枚举这些情况即可。经过程序计算,1——>1e7内可以由另外两个数的平方和构成的最多的是“5928325”,而组成它的对数仅有48个。
#include<bits/stdc++.h> #include<tr1/unordered_map> using namespace std; typedef long long ll; typedef pair<int,int> PII; const int MAXN = 1e5+10; const double EPS = 1e-12; const int mod = 1e9+7; //tr1::unordered_map<int,int>ump; vector<PII>G[MAXN*100]; int T,n,m,ct,cas; int p1[MAXN<<1],p2[MAXN<<1]; int val[6005][6005]; bool vis[6005][6005],flag[10005]; int main() { for(int i=0;i<=1e4;i++){ for(int j=0;j<=1e4;j++){ if(i*i+j*j>1e7)break; if(i==j){ if(flag[i])continue; else flag[i]=1; } G[i*i+j*j].push_back(PII(i,j)); } } scanf("%d",&T); while(T--){ printf("Case #%d: ",++cas); scanf("%d %d",&n,&m); int x,y;ll w,k; for(int i=1;i<=n;i++){ scanf("%d %d %lld",&x,&y,&w); vis[x][y]=1; val[x][y]=w; p1[++ct]=x;p2[ct]=y; } ll lastans=0; while(m--){ int op; scanf("%d %d %d",&op,&x,&y); x=(x+lastans)%6000+1; y=(y+lastans)%6000+1; if(op==1){ scanf("%lld",&w); vis[x][y]=1; val[x][y]=w; p1[++ct]=x;p2[ct]=y; } else if(op==2){ vis[x][y]=val[x][y]=0; } else if(op==3){ scanf("%lld %lld",&k,&w); for(int ii=0;ii<G[k].size();ii++){ PII p=G[k][ii]; int xx[3],yy[3]; xx[1]=x+p.first;yy[1]=y+p.second; xx[2]=x-p.first;yy[2]=y-p.second; for(int i=1;i<=2;i++){ if(xx[i]>6000||xx[i]<1)continue; if(i==2&&xx[i]==xx[i-1])continue; for(int j=1;j<=2;j++){ if(yy[j]>6000||yy[j]<1)continue; if(j==2&&yy[j]==yy[j-1])continue; if(vis[xx[i]][yy[j]])val[xx[i]][yy[j]]+=w; } } } } else{ scanf("%lld",&k); ll ans=0; for(int ii=0;ii<G[k].size();ii++){ PII p=G[k][ii]; int xx[3],yy[3]; xx[1]=x+p.first;yy[1]=y+p.second; xx[2]=x-p.first;yy[2]=y-p.second; for(int i=1;i<=2;i++){ if(xx[i]>6000||xx[i]<1)continue; if(i==2&&xx[i]==xx[i-1])continue; for(int j=1;j<=2;j++){ if(yy[j]>6000||yy[j]<1)continue; if(j==2&&yy[j]==yy[j-1])continue; if(vis[xx[i]][yy[j]])ans+=val[xx[i]][yy[j]]; } } } printf("%lld ",ans); lastans=ans; } } for(int i=1;i<=ct;i++) vis[p1[i]][p2[i]]=val[p1[i]][p2[i]]=0; ct=0; } }