2019牛客多校 Round4
Solved:3
Rank:331
B xor
题意:5e4个集合 每个集合最多32个数
5e4个询问 询问l到r个集合是不是都有一个子集的xor和等于x
题解:在牛客多校第一场学了线性基 然后这个题就是求线性基的交 如果一个区间都能表示x 那么就表示这个区间内所有线性基的交能表示x
用线段树维护这个东西 然后线性基交是抄的板子
#include <bits/stdc++.h>
using namespace std;
typedef long long ll; int n, m;
ll a[50005][35];
struct node {
ll val[35];
}; node lb[200005], t1, t2;
node merge(node A, node B) {
node res;
for(int i = 0; i <= 31; i++) t1.val[i] = t2.val[i] = A.val[i], res.val[i] = 0;
for(int i = 0; i <= 31; i++) {
ll x = B.val[i], t = 0;
if(!x) continue; int j = i;
for(; j >= 0; j--) {
if(x & (1LL << j)) {
if(t1.val[j]) x ^= t1.val[j], t ^= t2.val[j];
else break;
}
}
if(!x) res.val[i] = t;
else t1.val[j] = x, t2.val[j] = t;
}
return res;
} void build(int l, int r, int rt) {
for(int i = 0; i <= 31; i++) lb[rt].val[i] = 0;
if(l == r) {
for(int i = 1; i <= a[l][0]; i++) {
ll tmp = a[l][i];
for(int j = 31; j >= 0; j--) {
if(tmp & (1LL << j)) {
if(!lb[rt].val[j]) {
lb[rt].val[j] = tmp;
break;
}
tmp ^= lb[rt].val[j];
}
}
}
return;
} int mid = l + r >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
lb[rt] = merge(lb[rt << 1], lb[rt << 1 | 1]);
} bool ask(int rt, ll va) {
for(int i = 31; i >= 0; i--) {
if(va & (1LL << i)) va ^= lb[rt].val[i];
}
return va == 0;
} bool query(int ql, int qr, ll val, int l, int r, int rt) {
if(ql <= l && qr >= r) return ask(rt, val); bool res = 1;
int mid = l + r >> 1;
if(ql <= mid) res &= query(ql, qr, val, l, mid, rt << 1);
if(qr > mid) res &= query(ql, qr, val, mid + 1, r, rt << 1 | 1);
return res;
} int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%lld", &a[i][0]);
for(int j = 1; j <= a[i][0]; j++) scanf("%lld", &a[i][j]);
}
build(1, n, 1);
for(int i = 1; i <= m; i++) {
int a, b; ll c;
scanf("%d%d%lld", &a, &b, &c);
if(query(a, b, c, 1, n, 1)) puts("YES");
else puts("NO");
}
return 0;
}
B xor
C sequence
题意:给定a,b两个数组 求所有l,r中 最大的 a的最小值*b的区间和
题解:存一下每个点作为最小值 左右两边的最大最小连续子序列
比如每个点左边的最大连续子序列可以由在他左边的点转移过来 这个转移是具有单调性的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 3e6 + 5; int n;
int a[MAXN];
int b[MAXN];
ll sum[MAXN];
ll lz[MAXN], rz[MAXN], lf[MAXN], rf[MAXN];
int lpos[MAXN], rpos[MAXN]; int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++) scanf("%d", &b[i]), sum[i] = sum[i - 1] + 1LL * b[i]; ll ans = 1LL * a[1] * b[1];
lpos[1] = 0; lz[1] = lf[1] = 0;
for(int i = 2; i <= n; i++) {
int pos = i - 1;
lz[i] = lf[i] = 0;
while(pos >= 1 && a[i] <= a[pos]) {
lz[i] = max(lz[i], lz[pos] + sum[i - 1] - sum[pos - 1]);
lf[i] = min(lf[i], lf[pos] + sum[i - 1] - sum[pos - 1]);
pos = lpos[pos];
}
lpos[i] = pos;
} rpos[n] = n + 1; rz[n] = rf[n] = 0;
for(int i = n - 1; i >= 1; i--) {
int pos = i + 1;
rz[i] = rf[i] = 0;
while(pos <= n && a[i] <= a[pos]) {
rz[i] = max(rz[i], rz[pos] + sum[pos] - sum[i]);
rf[i] = min(rf[i], rf[pos] + sum[pos] - sum[i]);
pos = rpos[pos];
}
rpos[i] = pos;
} for(int i = 1; i <= n; i++) {
if(a[i] > 0) {
ans = max(ans, (lz[i] + rz[i] + 1LL * b[i]) * a[i]);
} else ans = max(ans, (lf[i] + rf[i] + 1LL * b[i]) * a[i]);
}
printf("%lld\n", ans);
return 0;
}
C sequence
D triples I
题意:把一个数最少表示成几个数的 or和
题解:如果这个数不是三的倍数的话 那么最多用两个数也可以构造出来了 题目保证有解
然后二进制下瞎逼搞搞 在算第i位大小时1没开LL wa死
#include <bits/stdc++.h>
using namespace std;
typedef long long ll; ll val1[70];
ll val2[70];
int main() {
int T;
scanf("%d", &T);
while(T--) {
ll n; scanf("%lld", &n);
int cnt1 = 0, cnt2 = 0;
for(ll i = 0; i <= 60; i++) {
if((n & (1LL << i)) == (1LL << i)) {
if((1LL << i) % 3 == 1LL) val1[++cnt1] = (1LL << i);
else val2[++cnt2] = (1LL << i);
}
}
if(n % 3 == 0) printf("1 %lld\n", n);
else if(n % 3 == 1) {
if(cnt1 && cnt2) printf("2 %lld %lld\n", n - val1[1], val1[1] + val2[1]);
else if(cnt1) printf("2 %lld %lld\n", n - val1[1], n - val1[2]);
else if(cnt2) printf("2 %lld %lld\n", n - val2[1] - val2[2], val2[1] + val2[2] + val2[3]);
} else {
if(cnt1 && cnt2) printf("2 %lld %lld\n", n - val2[1], val1[1] + val2[1]);
else if(cnt2) printf("2 %lld %lld\n", n - val2[1], n - val2[2]);
else if(cnt1) printf("2 %lld %lld\n", n - val1[1] - val1[2], val1[1] + val1[2] + val1[3]);
}
}
return 0;
}
D triples I
E triples II (DP)
题意:给一个数a 求用n个是三的倍数的数把它与出来的方案数
题解:根本想不出来是DP.... 一个数的二进制有的位(单看这一位)是%3=1的 有的是%3=2的
这里引用一个题解子集的定义:如果a中为1的二进制位在b中也都为1,我们称a是b的'子集'
dp[i][j]表示有i个%3=1 j个%3=2的数的 且是三的倍数的子集数量 这个东西是可以预处理来的
然后统计答案的时候 因为算的是子集 所以里面有不合法的子集.. 要把不合法的容斥搞出去
以后多复习几遍....
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353; ll pow_mod(ll x, ll y) {
ll res = 1;
while(y) {
if(y & 1) res = res * x % mod;
x = x * x % mod;
y >>= 1;
}
return res;
} ll dp[40][40];
ll c[40][40]; int main() {
c[0][0] = 1;
for(int i = 1; i <= 35; i++) {
c[i][0] = 1;
for(int j = 1; j <= i; j++) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
} for(int i = 0; i <= 35; i++) {
for(int j = 0; j <= 35; j++) {
for(int x = 0; x <= i; x++) {
for(int y = 0; y <= j; y++) {
if((x + y * 2) % 3 == 0) dp[i][j] = (dp[i][j] + c[i][x] * c[j][y] % mod) % mod;
}
}
}
} int T;
scanf("%d", &T);
while(T--) {
int cnt1 = 0, cnt2 = 0;
ll n, a;
scanf("%lld %lld", &n, &a);
for(int i = 0; i <= 61; i++) {
if(a & (1LL << i)) {
if(i & 1) cnt2++;
else cnt1++;
}
} ll ans = 0;
for(int i = cnt1 + cnt2; i >= 0; i--) {
ll tmp = 0;
for(int j = 0; j <= cnt1; j++) {
if(i - j > cnt2 || i < j) continue;
tmp += c[cnt1][j] * c[cnt2][i - j] % mod * pow_mod(dp[j][i - j], n) % mod;
tmp %= mod;
}
if((cnt1 + cnt2 - i) & 1) tmp = -tmp;
ans = (ans + tmp + mod) % mod;
}
printf("%lld\n", ans);
}
return 0;
}
E triples II
2019牛客多校 Round4的更多相关文章
- 2019牛客多校第一场 I Points Division(动态规划+线段树)
2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...
- 2019牛客多校第二场 A Eddy Walker(概率推公式)
2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- 2019牛客多校第一场E ABBA(DP)题解
链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 ABBA 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语 ...
- 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数
目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...
- 2019牛客多校第四场 A meeting
链接:https://ac.nowcoder.com/acm/contest/884/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...
- [2019牛客多校第二场][G. Polygons]
题目链接:https://ac.nowcoder.com/acm/contest/882/G 题目大意:有\(n\)条直线将平面分成若干个区域,要求处理\(m\)次询问:求第\(q\)大的区域面积.保 ...
- 2019 牛客多校第一场 D Parity of Tuples
题目链接:https://ac.nowcoder.com/acm/contest/881/D 看此博客之前请先参阅吕凯飞的论文<集合幂级数的性质与应用及其快速算法>,论文中很多符号会被本文 ...
- 2019牛客多校第二场D-Kth Minimum Clique
Kth Minimum Clique 题目传送门 解题思路 我们可以从没有点开始,把点一个一个放进去,先把放入一个点的情况都存进按照权值排序的优先队列,每次在新出队的集合里增加一个新的点,为了避免重复 ...
随机推荐
- fastjson复现项目代码
详情请见:https://www.cnblogs.com/yunmuq/p/14268028.html 以下是代码 // FastjsonDemo.java package test; import ...
- 一文读懂 SuperEdge 边缘容器架构与原理
前言 superedge是腾讯推出的Kubernetes-native边缘计算管理框架.相比openyurt以及kubeedge,superedge除了具备Kubernetes零侵入以及边缘自治特性, ...
- Openstack Nova 添加计算节点(六.一)
Openstack Nova 添加计算节点(六.一) # 重要的两点: 1 时间同步 2 yum 源 # 安装软件: yum install openstack-selinux openstack-n ...
- Haproxy-1.8.20 编译安装:
1 ) haproxy-1.8.20 : # 1.1 ) 安装Haproxy的依赖关系: yum install gcc gcc-c++ glibc glibc-devel pcre pcre-dev ...
- python模块/文件/日期时间
文件操作:
- mysql—make_set函数
使用格式:MAKE_SET(bits,str1,str2,-) 1 返回一个设定值(含子字符串分隔字符串","字符),在设置位的相应位的字符串.str1对应于位0,str2到第1位 ...
- oracle编译表上失效USERDBY脚本
对表进行DLL操作之后,依赖这个表的一些存储过程,触发器等会失效,可以用下边的脚本进行重编译 /* Formatted on 2020/7/8 上午 09:31:31 (QP5 v5.163.1008 ...
- 浅谈JavaScript代码性能优化
可以通过https://jsbench.me/测试网站完成性能测试. 一.慎用全局变量 1.全局变量定义在全局执行上下文,是所有作用域链的顶端,在局部作用域中没找到的变量都会到全局变量中去查找,所以说 ...
- Java自学笔记1206
字符串比较string1.equals(string2) 代码如下: 1 package Demo_1206; 2 3 import java.util.Scanner; 4 5 public cla ...
- 迈凯伦765LT/600LT/720S/650S/570S维修手册电路图Mclaren车间手册接线图
全套迈凯伦维修手册电路图Mclaren车间手册线路图:语言:English,German,French,Spanish,Chinese,Japanese.McLaren迈凯伦新GT维修手册电路图零配件 ...