sb atcoder 提前比赛时间/fn/fn/fn……sb atcoder 还我 rating/zk/zk/zk

A

签到题,枚举位数 \(+\) 前导 \(1\) 个数然后随便算算贡献即可,时间复杂度 \(\log^2_{10}(n)\)

B

u1s1 这个 B 感觉比一般的 B 难不少啊……

考虑贪心。首先第一位我们随便钦定 \(n\) 个 \(0\),\(n\) 个 \(1\) 和 \(n\) 个 \(2\),那么后面的位我们肯定会贪心地让第一位填 \(2\) 的都填 \(0\),第一位填 \(0/1\) 的自然不用管它们因为我们后面自然有办法为它们填数,但是这样会导致字符串出现重复的情况,怎么解决呢?如果我们发现目前不能区分出来的字符串个数 \(>3^{l-i}\),其中 \(i\) 表示当前填到了第几位,那么我们就贪心地依次填上 \(0000...0,000...1,\cdots,1111...11\),然后把最后的零头放到那“不能被区分出来的字符串集合”中即可。

可能讲得有点玄乎,看代码可能会比较好理解。

const int MAXN=1.5e5;
int n,l,pw3[18];
string s[MAXN+5];
int main(){
scanf("%d%d",&n,&l);
for(int i=(pw3[0]=1);i<=l;i++) pw3[i]=pw3[i-1]*3;
vector<int> id;
for(int i=1;i<=n;i++) id.pb(i);int cur=n;
for(int i=1;i<=n;i++) s[i].pb('0'),s[i+n].pb('1'),s[i+n+n].pb('2');
for(int _=2;_<=l;_++){
cur=id.size();
if(cur<=pw3[l-_]){
for(int x:id) s[x].pb('2'),s[x+n].pb('1'),s[x+n+n].pb('0');
} else if(cur<=pw3[l-_]*2) {
for(int i=0;i<pw3[l-_];i++){
int x=id[i];
// printf("%d\n",x);
s[x].pb('2');s[x+n].pb('1');s[x+n+n].pb('0');
for(int j=0;j<l-_;j++){
s[x].pb('0'+(i/pw3[j]%3));
s[x+n].pb('0'+(i/pw3[j]%3));
s[x+n+n].pb('0'+(i/pw3[j]%3));
}
} vector<int> nw;
for(int i=pw3[l-_];i<id.size();i++){
int x=id[i];
// printf("%d\n",x);
s[x].pb('0');s[x+n].pb('2');s[x+n+n].pb('1');
nw.pb(x);
} id=nw;
} else {
for(int i=0;i<pw3[l-_];i++){
int x=id[i];
s[x].pb('2');s[x+n].pb('1');s[x+n+n].pb('0');
for(int j=0;j<l-_;j++){
s[x].pb('0'+(i/pw3[j]%3));
s[x+n].pb('0'+(i/pw3[j]%3));
s[x+n+n].pb('0'+(i/pw3[j]%3));
}
}
for(int i=pw3[l-_];i<pw3[l-_]*2;i++){
int x=id[i];
s[x].pb('0');s[x+n].pb('2');s[x+n+n].pb('1');
for(int j=0;j<l-_;j++){
s[x].pb('0'+(i/pw3[j]%3));
s[x+n].pb('0'+(i/pw3[j]%3));
s[x+n+n].pb('0'+(i/pw3[j]%3));
}
} vector<int> nw;
for(int i=pw3[l-_]*2;i<id.size();i++){
int x=id[i];
s[x].pb('1');s[x+n].pb('0');s[x+n+n].pb('2');
nw.pb(x);
} id=nw;
}
}
for(int i=1;i<=n*3;i++) cout<<s[i]<<endl;
return 0;
}

C

请问您见过几个 arc C 被评到 2000+

首先考虑一个非常朴素的做法,我们先事先将 \(X\) 减 \(1\),然后每次从高位到低位一位一位考虑,如果当前 \(X\) 等于零那就直接 break,否则如果当前 \(X\le 2^{n-l}\),其中 \(l\) 为当前考虑的位,那么我们就在这一位上填 \(0\) 并将 \(X\) 减一,否则我们就在这一位上填 \(1\) 并将 \(X\) 减去 \(2^{n-l}\)

然后就是我降智的地方了。由于这题 \(X\) 很大需要高精度,因此我以为直接减 \(1\) 复杂度会退化到平方,于是想着打各种标记之类的奇怪玩意儿,WA 了好几发,事实上直接减 \(1\) 复杂度是正确的,感性理解一下不难发现当你进行一次减 \(1\) 之后退了很多很多位,那么在接下来很长一段时间内就不可能再退这么多位,如果理性证明地大概就 \(\sum\limits_{i=0}^{\log_2(n)}\lfloor\dfrac{n}{2^i}\rfloor=\mathcal O(n)\),因此总时间复杂度也是 \(\mathcal O(n)\)

D

考虑 \(c_i=a_i\oplus b_i\),那么不难发现对于一组 \(i,j\),\(a_i\oplus a_j\) 与 \(b_i\oplus b_j\) 从高到低第一个值不同的位就是 \(c_i\oplus c_j\) 二进制下的 significant bit,下文中称其为第 \(j\) 位,因此 \(\min(a_i\oplus a_j,b_i\oplus b_j)\) 取到 \(a_i\oplus a_j\) 当且仅当 \(a_i\oplus a_j\) 第 \(d\) 位为 \(1\)。

我们再考虑这样一个问题,给定序列 \(a\) 求它们两两异或和的和,01-trie 是一种方法,事实上我赛时一开始也考虑了这个做法,但是有一种更简单的做法是你考虑每一位的贡献,我们对于每一位记录一下有多少个数这一位为 \(0\),有多少个数这一位为 \(1\),这样可以 \(\mathcal O(1)\) 计算每一位的贡献。

接下来考虑原问题。我们将所有 \(c_i\) 插入 01-trie,然后对于 \(c_i\) 每一个为 \(1\) 的位 \(d\),我们在其对应的 01-trie 的节点上开 4 个长度为 \(\log(n)\) 的数组,下标为 \(j\) 的位置分别维护这样几个信息:对于经过这个节点且 \(c_i\) 为 \(1\) 的 \(i\),有多少个:

  • \(a_i\) 第 \(d\) 位为 \(0\) 的 \(i\),满足 \(a_i\) 的第 \(j\) 位为 0/1
  • \(a_i\) 第 \(d\) 位为 \(0\) 的 \(i\),满足 \(b_i\) 的第 \(j\) 位为 0/1
  • \(a_i\) 第 \(d\) 位为 \(1\) 的 \(i\),满足 \(a_i\) 的第 \(j\) 位为 0/1
  • \(a_i\) 第 \(d\) 位为 \(1\) 的 \(i\),满足 \(b_i\) 的第 \(j\) 位为 0/1

这样在遍历 01-trie 计算贡献的过程中,我们考虑计算一个 \(i\) 对答案的贡献时,可以考虑 \(c_i\) 所有为 \(0\) 的位,然后通过预处理的信息在单次 \(\mathcal O(\log n)\) 的时间内计算贡献。

记得加上 \(c_i=c_j\) 的贡献,这一部分的计算是 trivial 的,直接对每一种 \(c_i\) 重复一遍上面弱化版的过程即可。

时间复杂度 \(n\log^2n\)。

const int MAXN=262144;
const int LOG_N=18;
const int MAXP=2097152;
int n,A[MAXN+5],B[MAXN+5],C[MAXN+5];
int ch[MAXP+5][2],cnt[4][MAXP+5][LOG_N+2][2],rt=0,ncnt=0;
vector<int> pc[MAXN+5];
ll res=0;
void insert(int &k,int v,int dep,int a,int b){
if(!k) k=++ncnt;if(!~dep) return;
insert(ch[k][v>>dep&1],v,dep-1,a,b);
if(v>>dep&1){
if(a>>dep&1){
for(int j=0;j<LOG_N;j++) cnt[0][ch[k][v>>dep&1]][j][a>>j&1]++;
for(int j=0;j<LOG_N;j++) cnt[1][ch[k][v>>dep&1]][j][b>>j&1]++;
} else {
for(int j=0;j<LOG_N;j++) cnt[2][ch[k][v>>dep&1]][j][a>>j&1]++;
for(int j=0;j<LOG_N;j++) cnt[3][ch[k][v>>dep&1]][j][b>>j&1]++;
}
}
}
void query(int k,int v,int dep,int a,int b){
if(!k||!~dep) return;
query(ch[k][v>>dep&1],v,dep-1,a,b);
if(~v>>dep&1){
int c=ch[k][~v>>dep&1];
if(!c) return;
// printf("%d %d %d %d %d\n",v,dep,c,a,b);
if(a>>dep&1){
for(int j=0;j<LOG_N;j++) res+=1ll*cnt[0][c][j][~a>>j&1]*(1<<j);
for(int j=0;j<LOG_N;j++) res+=1ll*cnt[3][c][j][~b>>j&1]*(1<<j);
} else {
for(int j=0;j<LOG_N;j++) res+=1ll*cnt[1][c][j][~b>>j&1]*(1<<j);
for(int j=0;j<LOG_N;j++) res+=1ll*cnt[2][c][j][~a>>j&1]*(1<<j);
}
}
}
int cnt0[MAXN+5][LOG_N+2][2];
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]),C[i]=A[i]^B[i],pc[C[i]].pb(i);
for(int i=1;i<=n;i++) insert(rt,C[i],LOG_N-1,A[i],B[i]);
for(int i=1;i<=n;i++) for(int j=0;j<LOG_N;j++)
cnt0[C[i]][j][A[i]>>j&1]++;
// for(int i=1;i<=n;i++) printf("%d\n",c[i]);
for(int i=0;i<MAXN;i++){
ll s=0;
for(int id:pc[i]) for(int j=0;j<LOG_N;j++)
s+=1ll*cnt0[i][j][~A[id]>>j&1]*(1<<j);
s>>=1;res+=s;
}
for(int i=1;i<=n;i++) query(rt,C[i],LOG_N-1,A[i],B[i]);
printf("%lld\n",res);
return 0;
}

E

并没有自己想出来,搬运官方题解 ing

首先考虑如果我们想要尽量让大的数都在最终的 \(s\) 中那该怎么选择每次插入的数。显然按 \(1,2,3,\cdots,A\) 的顺序插入肯定是最优的。因此我们假设 \(b_1,b_2,\cdots,b_{A-B}\) 为按 \(1,2,3,\cdots,A\) 顺序插入后剩余的数组成的集合,其中 \(b_i<b_{i+1}\)。

我们再假设 \(c_1,c_2,\cdots,c_{A-B}(c_i<c_{i+1})\) 为按某种顺序插入后剩余的数组成的集合,那么我们不妨猜测 \(c_i\le b_i(i\in[1,A-B])\)。我们假设 \(p_1,p_2,\cdots,p_{B}\) 为按 \(1,2,3,\cdots,A\) 中不在剩余集合中的数组成的集合,\(q_1,q_2,\cdots,q_B\) 为按 \(c_1,c_2,\cdots,c_{A-B}\) 对应的顺序插入后不在剩余集合中的数组成的集合,其中 \(p_i<p_{i+1},q_i<q_{i+1}\),然后对于第 \(i\) 次插入考虑这样构造:

  • 如果 \(\exists j,s.t.b_j=i\),那么我们此次插入中插入 \(c_j\),其中 \(b_j=i\)。
  • 否则必然 \(\exists j,s.t.p_j=i\),我们就插入 \(q_j\)。

不难证明最后得到的数就是 \(c_1,c_2,\cdots,c_{A-B}\)。因此 \(c_1,c_2,\cdots,c_{A-B}\) 可以作为最终集合存在的充要条件是 \(\forall i\in[1,A-B],c_i\le b_i\)。到这里事情就变得很 trivial 了。\(dp_{i,j}\) 表示考虑了前 \(i\) 个数,\(c_i=j\) 的合法的 \(c\) 的个数,前缀和优化 DP 即可,时间复杂度 \(A^2\)。

AtCoder Regular Contest 127 题解的更多相关文章

  1. AtCoder Regular Contest 103 题解

    C-/\/\/\ #include<algorithm> #include<iostream> #include<cstdlib> #include<ioma ...

  2. AtCoder Regular Contest 127

    Portal B Description 给出\(n(\leq5\times10^4),L(\leq15)\),构造\(3n\)个不同\(L\)位的三进制数,使得在这\(3n\)个数的每一位上,0/1 ...

  3. Atcoder Regular Contest 123 题解

    u1s1 我是真的不知道为什么现场这么多人切了 D,感觉 D 对思维要求显然要高于其他 300+ 人切掉的 D 吧(也有可能是 Atc 用户整体水平提升了?) A 开 幕 雷 击(这题似乎 wjz 交 ...

  4. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

  5. AtCoder Regular Contest 096

    AtCoder Regular Contest 096 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个 ...

  6. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  7. AtCoder Regular Contest 092

    AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...

  8. AtCoder Regular Contest 093

    AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...

  9. AtCoder Regular Contest 094

    AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...

随机推荐

  1. Pycharm无法打开,双击没反应

    以下方案皆为引用,仅供参考. 方案一: 1.先声明一下,这种解决方法适用于任何版本的永久破解启动不了的情况(包括:2019版本的)2.下面直接切入正题之所以我们破解之后,不能正常启动的原因有两种:① ...

  2. 使用docker部署nginx并配置https

    我只有一台服务器,但我想在这台服务器上运行多个项目,怎么办? 总不能靠加端口区分吧? 百度和Google是个好东西,于是我找到了答案,使用nginx. 通过nginx,我可以给我的一台服务器配置两个域 ...

  3. CQL和SQL的CRUD操作比较

    数据进行CRUD操作时,CQL语句和SQL语句的异同之处. 1.建表 2.CRUD语句比较 3.总结 1.建表 在此之前先分别创建两张表,插入数据,用来测试然后进行比较 在SQL数据库里面创建表 在C ...

  4. 『学了就忘』Linux基础 — 4、VMware安装

    目录 1.VMware介绍 2.VMware主要特点 3.VMware建议配置 4.VMware安装 1.VMware介绍 VMware是一个虚拟PC的软件,可以在现有的操作系统上虚拟出一个新的硬件环 ...

  5. .Net(c#)汉字和Unicode编码互相转换实例

    {"name": "\u676d\u5dde", "href": "www.baidu.com"} 经常遇到这样内容的j ...

  6. python 模块 hashlib(提供多个不同的加密算法)

    hashlib是涉及安全散列和消息摘要,提供多个不同的加密算法借口,如SHA1.SHA224.SHA256.SHA384.SHA512.MD5等. import hashlib m = hashlib ...

  7. C++中gSOAP的使用

    目录 SOAP简介 gSOAP 准备工作 头文件 构建客户端应用程序 生成soap源码 建立客户端项目 构建服务端应用程序 生成SOAP源码 建立服务端项目 打印报文 SOAP测试 项目源码 本文主要 ...

  8. Loto实践干货(8) 实测 保险丝 用示波器带电流探头

    本文用LOTO示波器和5A的电流探头来实验两种常见类型的保险丝的保护曲线.一种是熔断型的,另一种是自恢复型的.我们通常需要在一些电路中对电流过大的情况做保护,比如防止用户把输出源短路,比如防止用户对电 ...

  9. ITextRenderers html生成pdf 分页+横向

    1.pdf横向生成问题:格式化html是加上 @page{size:297mm 210mm;} public static String formatPdfHtml(String html,Strin ...

  10. 2021 陇剑杯wp

    前言 这比赛应该叫应急响应比赛,而且flag交三次就不能交了,就因为我交错一道题然后差一道进线下,气死了. Jwt 2.1 jwt 题目提示 2.2 搜索username得到 10087#admin ...