传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4972
题意:
给一个方格纸,每一个格子有一个数val,q个询问,每次询问一个x,y,k,求(x,y),(x-k+1,y),(x,y-k+1)三个格子构成的三角形边上以及内部的所有格子的val的和。答案输出sigma((233)^(q-i)*fi)%(2^32),fi为第i次询问的答案。
题解:
图做的太丑了。。。。。凑合着看吧。。。
根据题意其实就是求上图黑色部分,黑色部分可以看成图一的灰加黑的正方形(画的一点不像正方形。。。)减去灰的部分,灰的部分其实是图二那个土黄色的部分减去图一剩下的那块有点黄又有点红的部分。
这样就分析完后可以不看图了,维护三个前缀和a,b,c。。a用来求某一块的矩形的总和,c用来求图二那个土黄色的部分,b用来求某一行的前缀和(方便求a,c),前缀和造出来了后,每次询问xjb写写就O(1)出答案啦。。
最后那个对2^32取模,其实开成unsigned int自然溢出就行了。。。
1 #include <bits/stdc++.h> 2 #define INF 0x3f3f3f3f 3 using namespace std; 4 typedef long long ll; 5 const int mod=1e9+7; 6 const int maxn=3e3+100; 7 const double eps=1e-10; 8 unsigned int A,B,C; 9 int n,m,q,x,y,k; 10 unsigned int a[maxn][maxn],b[maxn][maxn],c[maxn][maxn],d[3000000+100]; 11 inline unsigned int rng61(){ 12 A ^= A << 16; 13 A ^= A >> 5; 14 A ^= A << 1; 15 unsigned int t = A; 16 A = B; 17 B = C; 18 C ^= t ^ A; 19 return C; 20 } 21 int main() { 22 #ifdef ac 23 freopen("in.txt" , "r" , stdin); 24 // freopen("out.txt" , "w" , stdout); 25 #endif 26 d[0]=1; 27 for(int i=1;i<=3000000;++i)d[i]=d[i-1]*233; 28 scanf("%d%d%d%u%u%u", &n, &m, &q, &A, &B, &C); 29 for(int i = 1; i <= n; i++){ 30 for(int j = 1; j <= m; j++){ 31 a[i][j] = rng61();b[i][j]+=b[i][j-1]+a[i][j]; 32 c[i][j]=b[i][j]+c[i-1][j+1]; a[i][j]=b[i][j]+a[i-1][j]; 33 } 34 c[i][0]=c[i-1][1]; 35 } 36 37 unsigned int ans=0; 38 for(int i = 1; i <= q; i++){ 39 x = rng61() % n + 1; 40 y = rng61() % m + 1; 41 k = rng61() % min(x, y) + 1; 42 int x1=x-k,y1=y-k; 43 if(x1<0)x1=0;if(y1<0)y1=0; 44 unsigned tmp1=c[x][y1]-c[x1][y],tmp2=a[x][y1]-a[x1][y1],tmp3=tmp1-tmp2; 45 unsigned tmp4=a[x][y]-a[x1][y]-a[x][y1]+a[x1][y1],tmp5=tmp4-tmp3; 46 ans+=d[q-i]*tmp5; 47 } 48 printf("%u\n",ans); 49 return 0; 50 }
时间: 2024-10-14 19:11:26