分析
分析题意,我们可以发现它就是要让求 。而
是可以线性筛求出来的。所以现在问题就是如何维护矩阵中的
。因为
,所以可以考虑二维莫队这样的时间复杂度为
。这道题卡空间,要注意线性筛时可以不用额外数组记录
。
后话
关于牛客挑战赛42的题就算补完了,可以说这套题还是不错的,只是有些题面稍微卡空间,题目本身不是太难,但融合和了各个方面的知识,大赞。
代码
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
int read() {
int x = 0,f = 0;char ch = getchar();
while(!isdigit(ch)) {if(ch == '-')f = 1;ch = getchar();}
while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}
return f?-x:x;
}
const int N = 90,M = N*N*N*N,mod = 998244353;
int qpow(int x,int b) {
int a = 1;for(;b;b>>=1,x = 1LL * x * x % mod) {
if(b&1) a = 1LL * a * x % mod;
}
return a;
}
int a[N][N],n,m,limit,p[5000000],b[M],tot,pos[N];
int id[M],ans,Ans[100002],C[N*N];
struct Query{int l,r,u,d,id;}q[100002];
bool cmp(Query x,Query y) {
if(pos[x.l] != pos[y.l]) return x.l < y.l;
if(pos[x.r] != pos[y.r]) return x.r < y.r;
if(pos[x.u] != pos[y.u]) return x.u < y.u;
return x.d < y.d;
}
void add(int x) {
if(C[x] == 0) ans = (1LL * ans + (mod - id[b[x]]) % mod + mod) % mod;
C[x]++;
}
void del(int x) {
if(C[x] == 1) ans = (1LL * ans + id[b[x]] + mod) % mod;
C[x]--;
}
void work() {
ans = id[1] = 1;
for(int i = 2;i <= limit;i++) {
if(!id[i]) p[++p[0]] = i,id[i] = qpow(i,limit);
for(int j = 1;j <= p[0] && p[j] * i <= limit;j++) {
id[i * p[j]] = 1LL * id[p[j]] * id[i] % mod;
if(!(i % p[j])) break;
}
ans = (ans + id[i]) % mod;
}
}
int main()
{
n = read();limit = read();
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= n;j++) {
a[i][j] = read();b[++tot] = a[i][j];
}
}
sort(b+1,b+1+tot);tot = unique(b+1,b+1+tot) - b - 1;
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= n;j++) {
a[i][j] = lower_bound(b+1,b+1+tot,a[i][j]) - b;
}
}
work();
m = read();
int block = sqrt(n-1) + 1;
for(int i = 1;i <= n;i++) pos[i] = (i-1)/block + 1;
for(int i = 1;i <= m;i++) {
int x = read(),y = read(),X = read(),Y = read();
q[i].l = min(y,Y);q[i].r = max(y,Y);
q[i].u = min(x,X);q[i].d = max(x,X);q[i].id = i;
}
sort(q + 1,q + 1 + m,cmp);
for(int l = 1,u = 1,r = 0,d = 0,i = 1;i <= m;i++) {
while(l > q[i].l) {l--;for(int j = u;j <= d;j++) add(a[j][l]);}
while(r < q[i].r) {r++;for(int j = u;j <= d;j++) add(a[j][r]);}
while(u > q[i].u) {u--;for(int j = l;j <= r;j++) add(a[u][j]);}
while(d < q[i].d) {d++;for(int j = l;j <= r;j++) add(a[d][j]);}
while(l < q[i].l) {for(int j = u;j <= d;j++) del(a[j][l]);l++;}
while(r > q[i].r) {for(int j = u;j <= d;j++) del(a[j][r]);r--;}
while(u < q[i].u) {for(int j = l;j <= r;j++) del(a[u][j]);u++;}
while(d > q[i].d) {for(int j = l;j <= r;j++) del(a[d][j]);d--;}
Ans[q[i].id] = ans;
}
for(int i = 1;i <= m;i++) printf("%d\n",(Ans[i]+mod)%mod);
return 0;
}
京公网安备 11010502036488号