HDU 6336 Problem E. Matrix from Arrays(容斥原理)

Description

给出一个长度为 n n 的序列A,用以下代码生成一个无限大的矩阵

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;
    }
}

q q 次查询,每次查询一个子矩阵的元素和

Input

第一行一整数T表示用例组数,每组用例首先输入一整数 n n 表示A序列长度,之后输入 n n 个整数Ai表示该序列,之后输入一整数 q q 表示查询数,最后q行每行输入四个整数 x0,y0,x1,y1 x 0 , y 0 , x 1 , y 1 表示查询子矩阵 [x0,x1]×[y0,y1] [ x 0 , x 1 ] × [ y 0 , y 1 ] 元素和

(1T100.1n10,1Ai100,1q100,0x0x1108,1y0y1108) ( 1 ≤ T ≤ 100.1 ≤ n ≤ 10 , 1 ≤ A i ≤ 100 , 1 ≤ q ≤ 100 , 0 ≤ x 0 ≤ x 1 ≤ 10 8 , 1 ≤ y 0 ≤ y 1 ≤ 10 8 )

Output

输出查询子矩阵的元素和

Sample Input

1
3
1 10 100
5
3 3 3 3
2 3 3 3
2 3 5 8
5 1 10 10
9 99 999 1000

Sample Output

1
101
1068
2238
33076541

Solution

假设所生成无限矩阵行列从 1 1 开始,那么第i行第 j j 列的元素编号应为B(i,j)=A[((i+j2)(i+j1)2+i1)%n],根据这个显然知道 B(i,j)=B(2sn+i,2tn+j) B ( i , j ) = B ( 2 s n + i , 2 t n + j ) ,故左上角 2n2n 2 n ⋅ 2 n 的小矩阵是整个大矩阵的循环节,预处理出该小矩阵之后即可快速求出左上角开始的任意一个大矩阵的和,之后由容斥原理即可得到一个子矩阵的和

Code

#include<cstdio>
using namespace std;
typedef long long ll;
#define y2 yy2
int T,n,q,A[100],s[21][21];
ll Solve(int x,int y)
{
    ll ans=(ll)(x/n)*(y/n)*s[n][n];
    ans+=(ll)(x/n)*s[n][y%n]+(ll)(y/n)*s[x%n][n]+s[x%n][y%n];
    return ans;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",&A[i]);
        int res=0;
        for(int i=1;i<=4*n+1;i++)
            for(int j=1;j<=i;j++)
            {
                if(j<=2*n&&i-j+1<=2*n)s[j][i-j+1]=A[res];
                res=(res+1)%n; 
            }
        n*=2;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                s[i][j]=s[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        scanf("%d",&q);
        while(q--)
        {
            int x1,x2,y1,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            printf("%lld\n",Solve(x2+1,y2+1)+Solve(x1,y1)-Solve(x1,y2+1)-Solve(x2+1,y1));
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值