題解 CF1614C Divan and bitwise operations
阿新 • • 發佈:2021-12-05
一開始讀錯題了以為給的是每一段的異或和
如果是異或和也能做
那就按位考慮,將所有段排序,若存在兩段的左/右端點相同(如 \([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; }