题目链接:点击这里
题目大意:
给定两个长度为
n
n
n 的序列
{
a
i
}
,
{
b
i
}
\{a_i\},\{b_i\}
{ai},{bi} ,定义
c
k
=
m
a
x
(
a
i
⋅
b
j
)
c_k=max(a_i·b_j)
ck=max(ai⋅bj) 其中
i
&
j
≤
k
i\&j \le k
i&j≤k,求
∑
i
=
1
n
−
1
c
i
m
o
d
998244353
\sum_{i=1}^{n-1}c_i \mod 998244353
∑i=1n−1cimod998244353
题目分析:
不难想到,我们可以先求出
i
&
j
=
k
i\&j=k
i&j=k 的
c
k
c_k
ck ,然后倒着扫一遍最大值就可以得到答案了。
而由于
i
&
j
=
k
i\&j=k
i&j=k ,所以
i
,
j
i,j
i,j 都是
k
k
k 的一个超集,然后我们就可以用
S
O
S
d
p
SOSdp
SOSdp 通过维护
i
,
j
i,j
i,j 的超集来维护出
i
&
j
=
k
i\&j=k
i&j=k 时的
c
k
c_k
ck ,时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
注意:由于
∣
a
i
,
b
i
∣
≤
1
e
9
|a_i,b_i|\le 1e9
∣ai,bi∣≤1e9 所以我们需要同时维护
a
i
,
b
i
a_i,b_i
ai,bi 的最大值和最小值来保证
c
k
c_k
ck 的正确性
具体细节见代码:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#define ll long long
#define inf 0x3f3f3f3f
#define int ll
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 1e6+5;
const int mod = 998244353;
const double pi = acos(-1);
const double eps = 1e-8;
int n,a[maxn],b[maxn],maxa[maxn],maxb[maxn],mina[maxn],minb[maxn],c[maxn];
void init(int n)
{
for(int i = 0;i <= n;i++)
{
maxa[i] = maxb[i] = -inf;
mina[i] = minb[i] = inf;
}
}
signed main()
{
int t = read();
while(t--)
{
n = read();
int len = log2(n)+1;
init(1<<len);
for(int i = 0;i < n;i++) a[i] = read(),maxa[i] = mina[i] = a[i];
for(int i = 0;i < n;i++) b[i] = read(),maxb[i] = minb[i] = b[i];
for(int j = 0;j < len;j++)
for(int i = 0;i < n;i++)
if(!(i>>j&1))
{
maxa[i] = max(maxa[i],maxa[i^(1<<j)]);
maxb[i] = max(maxb[i],maxb[i^(1<<j)]);
minb[i] = min(minb[i],minb[i^(1<<j)]);
minb[i] = min(minb[i],minb[i^(1<<j)]);
}
for(int i = 0;i < n;i++) c[i] = max({maxa[i]*maxb[i],maxa[i]*minb[i],mina[i]*maxb[i],mina[i]*minb[i]});
for(int i = n-2;~i;i--) c[i] = max(c[i],c[i+1]);
int ans = 0;
for(int i = 0;i < n;i++) ans = (ans+c[i])%mod;
cout<<(ans+mod)%mod<<endl;
}
return 0;
}