I love max and multiply(sosdp高位前缀和求超集)
I love max and multiply
problem6971
题意
Mr.I has two sequence Ai and Bi of length n,(0≤i≤n−1).
Define an array C of length n, where Ck=max{AiBj}, satisfying (i&j≥k).
& is the button under binary Bitwise AND operation.
Please calculate the value of ∑n−1i=0Ci, modulo 998244353.
题解
sosdp求高维前缀和,然后求超集,每一种情况都由上一种情况可以推出
即7\((111)_2\)可以推出1\((001)_2\),2\((001)_2\),3\((010)_2\),4\((100)_2\),5\((101)_2\),6\((110)_2\),而其中4\((100)_2\),2\((010)_2\),1\((001)_2\)不能直接推出,但可以通过6\((110)_2\),5\((101)_2\),3\((011)_2\)间接推出
AC代码
#include<bits/stdc++.h>
#define int long long
#define ll int
using namespace std;
const int mod=998244353;
const int inf=1ll<<62;
int getmax(int a,int b,int c,int d){
//最大*最大,最小*最小,最大*最小 求的就是最大了
int ans1=d*b,ans2=a*c,ans3=a*d,ans4=b*c;
return max(ans1,max(ans2,max(ans3,ans4)));
}
void slove(){
int n;
scanf("%lld",&n);
vector<int>a(n+10),b(n+10);
vector<int>minl(n*5,inf),maxl(n*5,-inf),minr(n*5,inf),maxr(n*5,-inf);
for(int i=0;i<n;i++)scanf("%lld",&a[i]),minl[i]=maxl[i]=a[i];
for(int i=0;i<n;i++)scanf("%lld",&b[i]),minr[i]=maxr[i]=b[i];
int cnt=0;
while(n>>cnt)cnt++;
cnt++;//求有几位二进制
//求超集
for(int i=n-1;i>=0;i--){//从后往前遍历,后可以影响前面的数据
for(int j=0;j<=cnt;j++){//遍历每一位
if((i>>j&1)){
//i^(1<<j)<=>i-(1<<j)
maxl[i^(1<<j)]=max(maxl[i],maxl[i^(1<<j)]);
minl[i^(1<<j)]=min(minl[i],minl[i^(1<<j)]);
maxr[i^(1<<j)]=max(maxr[i],maxr[i^(1<<j)]);
minr[i^(1<<j)]=min(minr[i],minr[i^(1<<j)]);
}
}
}
vector<int>ans(n+10);
ans[n]=-inf;
int res=0;
for(int i=n-1;i>=0;i--) {
ans[i] = max(ans[i + 1], getmax(minl[i], maxl[i], minr[i], maxr[i]));
res = ((res + ans[i]) % mod + mod) % mod;
}
printf("%lld\n",res);
return;
}
signed main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
int t;
scanf("%lld",&t);
while(t--)slove();
fclose(stdin);
fclose(stdout);
return 0;
}
//1
//4
//9 1 4 4
//5 4 1 9

浙公网安备 33010602011771号