Codeforces Round #685(Div2)
Contest Link Official Editorial
A. Subtract or Divide
给你一个数 \(n\) ,每一步可以做以下两个操作之一:
- 用一个不等于 \(n\) 的 \(n\) 的约数除 \(n\)
- \(n-1\)
问变成 \(1\) 的最小步数。
Solution
又是赛时乱搞……赛时一开始写了一个除了质数以外能除就除的东西,然后交上去 Wa on 2
;于是又加了一个奇数就减偶数就除的东西,两个取 \(\min\) ,就过了……(其实这个想法貌似就是正解……当时还挺担心会被 Hack )
如果 \(n\leq 3\) ,直接输出答案。
否则,如果 \(n\) 是奇数,那么 n-1
是偶数,然后可以直接变成 \(2\) ,答案是 \(3\) .
如果 \(n\) 是偶数,那就直接变 \(2\) ,答案是 \(2\) .
Code
//Author: RingweEH
int find( int x )
{
int lim=sqrt(x);
for ( int i=2; i<=lim; i++ )
if ( x%i==0 ) return x/i;
return -1;
}
int main()
{
int T=read();
while ( T-- )
{
int n=read(),sav=n; int cnt=0;
while ( n!=1 )
{
cnt++; int x=find(n);
if ( x==-1 ) n--;
else n/=x;
}
int cnt2=0; n=sav;
while ( n!=1 )
{
cnt2++; int x=find(n);
if ( (n&1) || (x==-1) ) n--;
else n/=x;
}
printf( "%d\n",min(cnt,cnt2) );
}
}
B. Non-Substring Subsequence
给定一个长度为 \(n\) 的01串 \(s\) 和 \(q\) 个询问。每个询问形如 \(l_i,r_i\) 要求:
- 求出 \(s\) 的一个 子序列 使其等于 \(s[l_i,r_i]\) 且不连续。
问是否存在这样的子序列。
Solution
其实想一下就会发现,如果找不到,那么肯定只有 \([l_i,r_i]\) 这一个连续的子序列。
如果找到了,说明至少能把 \([l_i,r_i]\) 的头往前移或者把尾往后移。(因为 \([l_i,r_i]\) 是相邻的,要是能移动肯定是满足能移动头尾的)
所以判断 \(s[1,l_i-1]\) 中是否存在 \(s[j]=s[l_i]\) 即可,\(r_i\) 同理。
Code
//Author: RingweEH
int l=read(),r=read(); bool fl=0;
for ( int i=1; i<l; i++ )
if ( s[i]==s[l] ) fl=1;
for ( int i=n; i>r; i-- )
if ( s[i]==s[r] ) fl=1;
fl ? printf( "YES\n" ) : printf( "NO\n" );
C. String Equality
给定两个由小写英文字符组成的字符串 \(a,b\) .对 \(a\) 可以进行两个操作:
- 交换两个相邻字符
- 把连续 \(k\) 个同样的字符变成其后继
问能否把 \(a\) 变成 \(b\) .
Solution
能交换字符说明不需要考虑顺序问题。记 \(cnta[c],cntb[c]\) 为 \(c\) 在 \(a,b\) 中出现的次数。
由题目可知,如果要改变字符只能变大不能变小。
所以正序扫一遍这两个数组,
- 如果 \(cnta[i]\ge cntb[i]\) ,如果多出来的部分不能被 \(k\) 整除,那么显然无解,因为你不可能把这部分变掉。否则,把这一部分累加进 \(cntk\) 里面,供后面不够的时候使用。(这样保证只能从前面往后面贡献)
- 如果 \(cnta[i]<cntb[i]\) ,如果少的部分不能整除同理。如果累计的 \(cntk\) 不够用了还是无解。否则把 \(cntk\) 减去 \((cntb[i]-cnta[i])/k\) 即可。
Code
//Author: RingweEH
n=read(); k=read(); scanf( "%s",sa ); scanf( "%s",sb );
for ( int i=0; i<n; i++ )
cnta[sa[i]-'a']++,cntb[sb[i]-'a']++;
int cntk=0; bool fl=1;
for ( int i=0; i<25; i++ )
{
if ( cnta[i]>=cntb[i] )
{
if ( ((cnta[i]-cntb[i])%k)!=0 ) { fl=0; break; }
cntk+=(cnta[i]-cntb[i])/k;
}
else
{
if ( ((cntb[i]-cnta[i])%k)!=0 ) { fl=0; break; }
int del=(cntb[i]-cnta[i])/k;
if ( del>cntk ) { fl=0; break; }
cntk-=del;
}
}
if ( fl ) printf( "Yes\n" );
else printf( "No\n" );
D. Circle Game
\(\text{Ashish}\) 先手,\(\text{Utkarsh}\) 后手。
在一个二维平面上,有一个棋子被放在 \((0,0)\) 处。每一步移动可以让 \(x\) 或者 \(y\) 坐标增加 \(k\) ,且每一步必须在以 \((0,0)\) 为圆心, \(d\) 为半径的圆内。不能移动判负。问谁必胜。
Solution
显然,一开始只要 \(Ashish\) 能动,\(Utkarsh\) 都能在另一维坐标上相应移动。最后会到达点 \((k\times z,k\times z)\) 。
这时候,如果 \((k\times z,k\times (z+1))\) 在圆内,那么先手胜;否则后手胜。
Code
//Author: RingweEH
ll d=read(),k=read(),z=1;
while ( sqr(z*k)*2<=sqr(d) ) z++; z--;
if ( sqr(z*k)+sqr(z*k+k)<=sqr(d) ) printf( "Ashish\n" );
else printf( "Utkarsh\n" );
E1+2. Bitwise Queries (Hard Version)
交互题。有三种询问形式:
AND i j
: \(a_i \& a_j\)OR i j
: \(a_i|a_j\)XOR i j
: \(a_i\oplus a_j\)
保证 \(a_i\in[0,n-1]\) 。要求在不超过 \(n+1\) 次询问中得到整个序列。
Solution
分两种情况讨论。首先,\(n-1\) 次询问 \(a[1]\oplus a[i]\) .
- 存在 \(a[x]=a[y]\) . 有两种可能,一种是出现 0 ,另一种是有两个结果相等。无论是哪种都可以把两个相等的数 \(\&\) 一下得到具体值,反推即可。
- 否则,显然每个数都是唯一的。必定存在一个数 \(a[x]\oplus a[1]=1\) ,然后询问 \(a[1]\text{ and } a[x]\) ;再找一个 \(a[y]\oplus a[1]=3\) ,如果 \(a[x]\text{ and }a[y]=1\) 说明 \(1\) 在 \(a[x]\) ,否则在 \(a[y]\) ,这样就得到了 \(a[1]\) ,进而可以推知全部的数。
Code
//Author: RingweEH
int get_query( int opt,int x,int y )
{
if ( opt==1 ) cout<<"AND "<<x<<" "<<y<<endl;
else if ( opt==2 ) cout<<"OR "<<x<<" "<<y<<endl;
else if ( opt==3 ) cout<<"XOR "<<x<<" "<<y<<endl;
cout.flush(); int tmp; cin>>tmp; return tmp;
}
int main()
{
cin>>n; sum[0]=1; int id=0;
for ( int i=2; i<=n; i++ )
{
int tmp=get_query( 3,1,i ); ans[i]=tmp;
if ( !sum[tmp] ) sum[tmp]=i;
else id=i;
}
if ( id )
{
int tmp=get_query( 1,sum[ans[id]],id );
ans[1]=ans[id]^tmp;
for ( int i=2; i<=n; i++ )
ans[i]^=ans[1];
}
else
{
int t1=get_query(1,sum[1],1),t2=get_query(1,sum[2],1);
int tmp=t1+t2%2;
for ( int i=1; i<=n; i++ )
ans[i]^=tmp;
}
cout<<"! ";
for ( int i=1; i<=n; i++ )
cout<<ans[i]<<' ';
return 0;
}
F. Nullify The Matrix
给定一个 \(n\times m\) 的矩阵,元素为非负数。轮流操作:
- 选一个非零点 \((r_1,c_1)\) 作为起点,一个点 \((r_2,c_2)\) 满足 \(r_2\ge r_1,c_2\ge c_1\) 作为终点。
- 将 \(a_{r_1,c_1}\) 的值减小为 \([0,a_{r_1,c_1}-1]\) 。
- 任选一条从开始点 \((r_1,c_1)\) 到结束点 \(r_2,c_2\) 的一条最短路,并修改路径上点为一个非负数。(最短路是单元格个数,每个单元格可以单独修改)
- 路径上的点不包含起点但包含终点。如果起始相同那么单元格的值减小。
当矩阵的数全部为 0 时,无法操作的一方输。问胜者。
Solution
结论:
令常数 \(d\) 为斜对角线上 \(r,c\) 坐标之和,\(xor(d)=a_{r_1,c_1}\oplus a_{r_2,c_2}\oplus...\oplus a_{r_n,c_n}(r_i+c_i==d)\) 。
如果对于所有的 \(d\) ,在游戏开始时有 \(xor(d)=0\) ,那么后手胜,否则先手必胜。(深刻感受到翻译的痛苦)
Let's consider diagonals \(d\) of the form \(r+c\) - the diagonals where the sum of row index (r) and column index (c) is constant. Then xor of a diagonal \(d\) will be \(xor(d)=a(r1,c1)⊕a(r2,c2)⊕...a(rn,cn)\) , such that \(r_1+c_1=d\) , \(r_2+c_2=d\) , .... \(r_n+c_n=d\) .
If \(0∀d,xor(d)=0\) at the start of the game, then Jeel wins. Else, Ashish wins.
\(Proof\) :设状态 \(S_1\) 为对于任意的 \(d\) ,\(xor(d)=0\) ;设状态 \(S_2\) 为存在 \(d\) 使得 \(xor(d)\neq 0\) .
\(Lemma1\) :对 \(S_1\) 中状态进行的任何操作都将转移到 \(S_2\) .由于起点不能在路径中被改变且在开头必须被改成一个 \([0,a_{r_1,c_1}-1]\) 之间的数,所以异或和一定不为0.
\(Lemma2\) :永远存在一种转移使得 \(S_2\) 中的状态能转移到 \(S_1\) 中。对于一个状态,如果其异或值不为 0 ,总能选择一个数,让它变小之后异或值为 0 .
发现 \(S_1\) 属于败集。那么如果初始状态属于 \(S_2\) ,先手就总能把败局留给后手,而后手只能把胜局留给先手。
复杂度 \(\mathcal{O}(n\times m)\) .
Code
//Author: RingweEH
int main()
{
int T=read();
while ( T-- )
{
memset( sum,0,sizeof(sum) );
n=read(); m=read();
for ( int i=1; i<=n; i++ )
for ( int j=1; j<=m; j++ )
{
a[i][j]=read(); sum[i+j]^=a[i][j];
}
bool fl=1;
for ( int i=1; i<=n+m; i++ )
fl&=(sum[i]==0);
if ( !fl ) printf( "Ashish\n" );
else printf( "Jeel\n" );
}
}
Codeforces Round #685(Div2)的更多相关文章
- Codeforces Round #539 div2
Codeforces Round #539 div2 abstract I 离散化三连 sort(pos.begin(), pos.end()); pos.erase(unique(pos.begin ...
- 【前行】◇第3站◇ Codeforces Round #512 Div2
[第3站]Codeforces Round #512 Div2 第三题莫名卡半天……一堆细节没处理,改一个发现还有一个……然后就炸了,罚了一啪啦时间 Rating又掉了……但是没什么,比上一次好多了: ...
- Codeforces Round#320 Div2 解题报告
Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Fin ...
- Codeforces Round #564(div2)
Codeforces Round #564(div2) 本来以为是送分场,结果成了送命场. 菜是原罪 A SB题,上来读不懂题就交WA了一发,代码就不粘了 B 简单构造 很明显,\(n*n\)的矩阵可 ...
- Codeforces Round #361 div2
ProblemA(Codeforces Round 689A): 题意: 给一个手势, 问这个手势是否是唯一. 思路: 暴力, 模拟将这个手势上下左右移动一次看是否还在键盘上即可. 代码: #incl ...
- Codeforces Round #626 Div2 D,E
比赛链接: Codeforces Round #626 (Div. 2, based on Moscow Open Olympiad in Informatics) D.Present 题意: 给定大 ...
- CodeForces Round 192 Div2
This is the first time I took part in Codeforces Competition.The only felt is that my IQ was contemp ...
- Codeforces Round #359 div2
Problem_A(CodeForces 686A): 题意: \[ 有n个输入, +\space d_i代表冰淇淋数目增加d_i个, -\space d_i表示某个孩纸需要d_i个, 如果你现在手里 ...
- Codeforces Round #360 div2
Problem_A(CodeForces 688A): 题意: 有d天, n个人.如果这n个人同时出现, 那么你就赢不了他们所有的人, 除此之外, 你可以赢他们所有到场的人. 到场人数为0也算赢. 现 ...
随机推荐
- 淘宝客?CPS技术是怎么实现的?
前言 微信搜[Java3y]关注这个有梦想的男人,点赞关注是对我最大的支持! 文本已收录至我的GitHub:https://github.com/ZhongFuCheng3y/3y,有300多篇原创文 ...
- Socket bind系统调用简要分析
主要查看linux kernel 源码:Socket.c 以及af_inet.c文件 1.1 bind分析 #include <sys/types.h> /* See NOTES */#i ...
- 僵尸进程与SIGCHLD信号
什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该 ...
- hibernate 基础知识
1.hibernate的配置文件,一般放在classpath的根目录下,默认命名为hibernate.cfg.xml,代码例子如下: <!DOCTYPE hibernate-configurat ...
- HTTP介绍(一)
超文本传输协议(HTTP)是一种用于分布式,协作式超媒体信息系统的应用程序层协议.HTTP是万维网(World Wide Web)数据通信的基础,超文本文档包括指向用户可以轻松访问的其他资源的超链接, ...
- 面试官:小伙子,你给我说一下Java Exception 和 Error 的区别吧?
前言 昨天在整理粉丝给我私信的时候,发现了一个挺有意思的事情.是这样的,有一个粉丝朋友私信问我Java 的 Exception 和 Error 有什么区别呢?说他在面试的时候被问到这个问题卡壳了,最后 ...
- 用Camtasia设计微课视频封面,让课程更加高大上
在网络时代,尤其现在疫情影响只能线上学习,微课的应用前景已经越来越广了.但是想把微课做好,只有内容与录制精细是不够的,还需要一个精美的封面来吸引学生.接下来,小编就用微课制作软件Camtasia 20 ...
- zabbix 用Telegram报警!!!
第一步:先在Telegram 注册个机器人!!! @BotFather在Telegram中添加联系人并按"开始",然后键入: /newbot输入你要新建的机器人名称在电报中@你的机 ...
- Linux查看并杀死被占用的端口
sudo apt-get install lsof //安装lsof sudo lsof -i:端口号 //查找对应的进程号 sudo kill -9 进程号 //杀死对应的进程
- python应用(3):启用集成开发工具pycharm
之前写了个python程序给自己用,写代码时用的是macvim(vim的一种),macvim是个编辑工具,由于我已经设置过对python等各种语言的支持特性,所以什么缩进.对齐.高亮之类的表现都有,写 ...