1. 程式人生 > 其它 >題解 CF1614C Divan and bitwise operations

題解 CF1614C Divan and bitwise operations

傳送門

一開始讀錯題了以為給的是每一段的異或和
如果是異或和也能做
那就按位考慮,將所有段排序,若存在兩段的左/右端點相同(如 \([l, r1],[l, r2]\))就斷成 \([l, r1], [r1+1, r2]\)
於是從小到大列舉欄位,樹狀陣列查詢區間異或和,若與給定不同就修改區間內的第一個位置使之相同
每個段都唯一對應一個“第一個位置”,所以可以構造出一個合法序列
按位拆開DP即可

現在給的是區間或了,可以參考官方題解

點選檢視程式碼
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m, tem;
const ll mod=1e9+7;
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}

signed main()
{
	int t=read();
	while (t--) {
		n=read(); m=read(); tem=0;
		for (int i=1; i<=m; ++i) read(), read(), tem|=read();
		printf("%lld\n", tem*qpow(2, n-1)%mod);
	}
	
	return 0;
}