I love max and multiply

参考:题解

Problem Description:

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 ∑Ci(i=0,1,…,n-1), modulo 998244353.

Input

The first line contains an integer T . Then T test cases follow.

Each test case contains three lines.

The first one contains an integer n— length of the array a.

The second one contains n integers A0,A1,A2,...,An−1

The third one contains n integers B0,B1,B2,...,Bn−1
 

Output

For each test case, output a single integer ans,where ans=∑Ci(i=0,…,n-1) modulo 998244353.

#include<iostream>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
const ll mod = 998244353;
const int inf = 1e9 + 7;
int A[N], B[N], a[N], b[N];
ll ans[N];
int main() {
	int T, n;
	cin >> T;
	while (T--) {
		cin >> n;


		//输入数组A  
		for (int i = 0; i < n; i++) {
			cin >> A[i];
			a[i] = A[i];
		}

		//输入数组B
		for (int i = 0; i < n; i++) {
			cin >> B[i];
			b[i] = B[i];
		}

		/*
		因为涉及负数 数组A存放最大数,数组a存放小数
		 A数组: 将n到m设置为 - inf
		  (举例:
		       n = 1001 
			   计算A[i](i = 1000)时会涉及A[1001]等
			   因此将A[1001]~A[1111]设置为 - inf, 不影响A[i]结果)
	    */
		int m = 1;
		while (m < n) m <<= 1;
		for (int i = n; i <= m; i++) {
			A[i] = -inf;
			B[i] = -inf;
			a[i] = inf;
			b[i] = inf;
		}

		/*
		  
		101:max{101,111}
		100:max{100,101,110}(=max{100,101,111,110})
		所以倒叙
		
		*/
		for (int i = n - 1; i >= 0; i--) {
			for (int j = 1; j < m; j <<= 1) {
				if (!(i & j)) {
					A[i] = max(A[i], A[i ^ j]);
					B[i] = max(B[i], B[i ^ j]);
					a[i] = min(a[i], a[i ^ j]);
					b[i] = min(b[i], b[i ^ j]);
				}
			}
		}
		ans[n] = -(ll)inf * inf;
		for (int i = n - 1; i >= 0; i--) {
			ans[i] = -(ll)inf * inf;
			ans[i] = max(ans[i], (ll)A[i] * B[i]);
			ans[i] = max(ans[i], (ll)A[i] * b[i]);
			ans[i] = max(ans[i], (ll)a[i] * B[i]);
			ans[i] = max(ans[i], (ll)a[i] * b[i]);
			ans[i] = max(ans[i], ans[i + 1]);
		}
		ll res = 0;
		for (int i = 0; i < n; i++) {
			res = (res + ans[i]) % mod;
		}
		res = (res + mod) % mod; /*ans[i]可能是负的*/
		cout << res << endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值