【bzoj4972】小Q的方格纸 前缀和

题目让O(1)预处理出来 类三角形边界及内部的和

根据这个图 就是一个大矩形-左边的绿色的矩形 - 蓝色的大三角形 + 右上角突出的蓝色的小三角形 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,l,r) for(int i=l;i<=r;i++)
const ll mod = 1LL<<32;
const int N = 3000+10;
unsigned int A,B,C;
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;
}

ll a[N][N], rect[N][N], tri[N][N];

int n, m, q ,x, y, k;
void input()
{
    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] = rng61();
}
ll pow_mod(ll x,ll n1) {
    ll res = 1;
    while (n1 > 0) {
        if(n1 & 1) res = res*x%mod;
        x = x*x%mod;
        n1/=2;
    }
    return res;
}


int main () {
    freopen("out.txt","w",stdout);
    input();
    //printf("---rect ---\n");
    rep(i,1,n) {
        rep(j,1,m) {
            rect[i][j] = rect[i-1][j] + rect[i][j-1] - rect[i-1][j-1] + a[i][j];
            //printf("%10lld ",rect[i][j]);
        }
        //puts("");
    }
    //printf("---rect ---\n");
    //printf("---tri ---\n");
    rep(i,1,n) {
        for(int j=m;j>=1;j--) {
            tri[i][j] = tri[i-1][j] + tri[i-1][j+1] - tri[i-2][j+1] + a[i][j];
            //printf("%10lld ",tri[i][j]);
        }
        //puts("");
    }
    //printf("---tri ---\n");
    ll res = 0;
    for(int i=1;i<=q;i++) {
        x = rng61() % n + 1;
        y = rng61() % m + 1;
        k = rng61() % min(x, y) + 1;
        ll ans = rect[x][y] - rect[x][y-k] - tri[x-1][y-k+1] + tri[x-k-1][y+1];
        res = res*233%mod + ans %mod;
        res %=mod;
    }
    cout << res <<endl;
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Draymonder/p/9497588.html