给出矩阵最上面一行和最左边一行, 点的值为 , , 要求计算矩阵内的元素 .
假设现在要求点 的答案, 上边界上的点 对 的贡献为
- 于是可以先利用已有条件求出 询问矩阵 的 上, 下边界 ,
- 然后利用 的 询问矩阵 上, 左边界预处理出整个矩阵, 处理询问即可 .
最坏时间复杂度 .
设 表示 所包含的 因子 的个数, 然后阶乘计算组合数时只需看因子的个数是否大于 即可, 具体看代码.
同时还要注意 数组要开 倍 .
#include<bits/stdc++.h>
#define reg register
const int maxn = (1<<17) + 105;
int K;
int Q;
int top[maxn];
int cnt[maxn<<1];
int left[maxn];
int A[105][105];
int C(int n, int m){ return cnt[n]-cnt[m]-cnt[n-m]<=0; }
int main(){
freopen("recursion.in", "r", stdin);
freopen("recursion.out", "w", stdout);
scanf("%d", &K); K = 1<<K;
for(reg int i = 2; i <= 100+K; i ++) scanf("%d", &top[i]);
for(reg int i = 2; i <= 100+K; i ++) scanf("%d", &left[i]);
for(reg int i = 1; i <= (100+K)*2; i ++){ // --
int tmp = i, tmp_2 = 0;
while(!(tmp & 1)) tmp >>= 1, tmp_2 ++;
cnt[i] = cnt[i-1] + tmp_2;
}
// for(reg int i = 1; i <= 100; i ++) printf("%d
", cnt[i]);
/*
for(reg int i = 1; i <= 100; i ++){ // a: (K+1, K+i)
for(reg int j = 2; j <= K+i; j ++) // b: (1, j)
A[1][i] ^= C(K+K+i-j-1, K-1)*top[j];
for(reg int j = 2; j <= K+i; j ++) // b: (j, 1)
A[1][i] ^= C(K+K+i-j-1, K+i-2)*left[j];
}
for(reg int i = 1; i <= 100; i ++){ // a:(K+i, K+1)
for(reg int j = 2; j <= K+i; j ++) // b: (1, j)
A[i][1] ^= C(K+i-1+K-j, K+i-2)*top[j];
for(reg int j = 2; j <= K+i; j ++) // b: (j, 1)
A[i][1] ^= C(K+i-j+K-1, K-1)*left[j];
}
*/
for(reg int i = 1; i <= 100; i ++){
int tot = K - 1;
for(reg int j = K+i; j >= 2; j --)
A[1][i] ^= top[j]*C(tot, K-1), tot ++;
tot = K + i - 1 - 1;
for(reg int j = K+1; j >= 2; j --)
A[1][i] ^= left[j]*C(tot, K+i-2), tot ++;
}
for(reg int i = 2; i <= 100; i ++){
int tot = K - 1;
for(reg int j = K+i; j >= 2; j --)
A[i][1] ^= left[j]*C(tot, K-1), tot ++;
tot = K + i - 2;
for(reg int j = K+1; j >= 2; j --)
A[i][1] ^= top[j]*C(tot, K+i-2), tot ++;
}
for(reg int i = 2; i <= 100; i ++)
for(reg int j = 2; j <= 100; j ++) A[i][j] = A[i-1][j] ^ A[i][j-1];
/*
for(reg int i = 2; i <= 100; i ++){
for(reg int j = 2; j <= 100; j ++)
printf("%d ", A[i][j]);
printf("
");
}
*/
scanf("%d", &Q);
while(Q --){
int n, m;
scanf("%d%d", &n, &m);
printf("%d
", A[n][m]);
}
return 0;
}