应该经常需要锻炼一下英语阅读理解能力和代码能力,所以以后还是需要多打打CF。

今天大概就是水一水找找感觉。

A. Neko Finds Grapes

$n$个箱子,$m$个钥匙 ($n,m \leq 10^6$),每个箱子有参数$a_i$,每个钥匙有参数$b_i$

当且仅当,$a_i + b_j \equiv 1 (mod 2)$,则说箱子和钥匙配对成功。

注意到,一个箱子只能和一个钥匙配对最多一次。

要求最大化配对数。

Solution : 直接统计即可,考虑配对只可能是奇数+偶数或者偶数+奇数。

所以答案必然是$\min\{ cnta_{奇} , cntb_{偶}\} +\min\{ cnta_{偶} , cntb_{奇}\}  $

# include <bits/stdc++.h>
using namespace std;
int cntA[],cntB[];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) {
int t; scanf("%d",&t);
cntA[t%]++;
}
for (int i=;i<=m;i++) {
int t; scanf("%d",&t);
cntB[t%]++;
}
int ans=min(cntA[],cntB[])+min(cntA[],cntB[]);
printf("%d\n",ans);
return ;
}

A.cpp

B. Neko Performs Cat Furrier Transform

定义在一个数$x(x\leq 10^6)$上的A,B两种操作,

A操作:$x=x \bigoplus  (2^n-1)$(其中$n$的值可以自己选定)

B操作:$x=x+1$

要求A,B两个操作交替进行,要求输出方案将$x$的最终值变成$2^m-1$即可。

要求步骤数不超过40步,但是不要求最短。

Solution:事实上A操作的意图是将数字的末若干位取反。B操作含义是将数最后一位+1,并且进位。

考虑一个贪心,如果每次取将第一个0出现的位置往低位取反,然后最后在末尾+1,那么每次至少消去第一个0出现的位置的一个0

所以必然2步就可以至少删去1个0,那么显然可以在40步内完成任务。

  本题主要需要注意,操作步数不一定是偶数,可能最后的B操作不做,操作步数是奇数的,需要特判。

# include <bits/stdc++.h>
using namespace std;
int base[];
int ttt[];
int getbit(int x)
{
int t=x,cnt=;
while (t) t/=,cnt++;
return cnt;
}
bool check(int x)
{
for (int i=;i<=;i++)
if (x==base[i]) return ;
return ;
}
int main()
{
int uuu=;
int x,ans=; scanf("%d",&x);
for (int i=;i<=;i++) base[i]=(<<i)-;
if (check(x)) {
puts(""); return ;
}
while (true) {
int p=getbit(x);
bool flag=false;
for (int i=p-;i>=;i--)
if (((<<i)&x)==) {
x=x^((<<(i+))-); ttt[++ttt[]]=i+; uuu++;
if (check(x)) flag=true;
if (flag) break;
x=x+; uuu++;
if (check(x)) flag=true;
if (flag) break;
break;
}
if (flag) break;
}
printf("%d\n",uuu);
for (int i=;i<=ttt[];i++)
printf("%d ",ttt[i]);
return ;
}

B.cpp

C. Neko does Maths

给出数$a,b(a,b\leq 10^9)$,要求先最小化$lcm(a+k,b+k)$的同时,最小化$k$的值。

Solution:不妨设$a>b$

显然$lcm(a+k,b+k)=\frac{(a+k)(b+k)}{gcd(a+k,b+k)}$

由辗转相减法可知$gcd(a,b)=gcd(b,a-b)$,

所以原式可化为$lcm(a+k,b+k)=\frac{(a+k)(b+k)}{gcd(b+k,a-b)}$

对于$a-b$的值是定值,那么我们就可以枚举$a-b$的因子$w$然后反过来O(1)求出最小的$k$就行了。

若$b \%  w = 0$ 那么 $k = 0$ 否则 $k = (\left \lfloor \frac{b}{w} \right \rfloor + 1)w-b$

复杂度$ O(\sqrt{a-b}) $

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+;
int n,A[N];
signed main()
{
int a,b; scanf("%lld%lld",&a,&b);
if (a<b) swap(a,b); int d=a-b;
for (int i=;i<=sqrt(d);i++)
if (d%i==) A[++n]=i,A[++n]=d/i;
int ans=0x7fffffffffffffff,pr=;
for (int i=;i<=n;i++) {
int w=A[i],k=(b%w)?(b/w+)*w-b:0ll;
if (ans>(a+k)*(b+k)/w) ans=(a+k)*(b+k)/w,pr=k;
}
cout<<pr<<'\n';
return ;
}

C.cpp

D. Neko and Aki's Prank

考虑一个长度为2n ($n \leq 1000$)的括号序列所在的字典树,一组合法的选边是任取一条边两端的两个点都不在边集中其他边中出现。

最大化选边集合的边数。 由于答案较大,对$10^9 + 7 $取模.

Solution :

考虑到括号序列所在的trie树,若两个括号序列前缀平衡数一定的时候,那么为了保证最后得到合法的括号序列,那么显然,其子树必然相等。

显然,我们不需要重复计算这些冗余的量。

考虑维护这个状态 , 考虑到确定一个等价的状态只需要确定当前序列总长度和当前平衡值即可。

我们这里对于当前括号序列平衡值的定义是:当前左括号数-右括号数。

显然,通过这两种状态就可以确定一些相互等价的点。这些状态的数目是$n^2$

考虑一个简单的dp,设$f[i][j]$表示当前括号序列长度为$i$(深度),左括号数-右括号数(平衡值)

考虑转移:

$ f[i][j] += f[i-1][j-1] $新增1个右括号
$ f[i][j] += f[i-1][j+1] $新增1个左括号

我们需要知道转移是否合法,即能否组成新的边,这取决于父亲节点$(i-1)$的合法性。

不妨设$g[i][j]$为$f[i][j]$意义下对于$(i,j)$的合法性 ,转移也非常显然 $g[i][j] = !(g[i-1][j-1]||g[i-1][j+1])$

所以若$ g[i][j] = 1$ 时 生成(i,j) 的方案会额外多1种。

所以转移方程可以写成

$ f[i][j] = f[i-1][j-1] + f[i-1][j+1] + g[i-1][j-1]||g[i-1][j+1]$
$ g[i][j] = !(g[i-1][j-1]||g[i-1][j+1])$

边界 $f[0][0]=0, g[0][0] = 1$

细节方面直接对于一个$ f[i][j] $显然需要满足$j \leq i$。

# include <bits/stdc++.h>
# define int long long
const int N=2e3+;
const int mo=1e9+;
int f[N][N]; bool g[N][N];
using namespace std;
signed main()
{
int n; scanf("%lld",&n); n<<=;
f[][]=,g[][]=true;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
{
int ret=,flag=;
if (j!=) ret=(ret+f[i-][j-])%mo,flag|=g[i-][j-];
if (j+<=i-) ret=(ret+f[i-][j+])%mo,flag|=g[i-][j+];
if (flag) f[i][j]=(ret+)%mo,g[i][j]=false;
else f[i][j]=ret%mo,g[i][j]=true;
}
printf("%lld\n",f[n][]);
return ;
}

D.cpp

E. Neko and Flashback

若有一个已知的$a_n$数组,对于$i \in [1,n-1]$ 定义$b_n , c_n $

即$b_i = min(a_i,a_{i+1}) , c_i=max(a_i,a_{i+1})$

现在给出的是乱序的$b,c$数组,询问是否能求出$a$数组,若能输出方案否则输出"-1"

Solution : 显然对于$b,c$两个数组所描述的数一定是相邻两个数。

也就是说给出这两个数组的目的是告诉选手那两个数是被放在相邻位置的。

对于第$i$组要求,表示数$b_i$和数$c_i$出于相邻位置,于是我们将其建一条无向边。

显然如果构成一组合法的序列,那么这些限制都需要满足,自然想到了欧拉路径(不重复经过所有边)

现在,这条路径上点表示的数就是所求的序列。

于是,我们只需要将点权离散化Fleury跑欧拉路径即可,复杂度大概是O(E)

这里只有$n-1$条边,所以总复杂度是$O(n)$

注意,图可能不是欧拉图,甚至不连通,甚至输入就不合法($a_i > b_i$)在这些情况下直接输出-1即可。

# include <bits/stdc++.h>
using namespace std;
const int N=1e6+;
int du[N],a[N],b[N],t[N],Path[N],T,n;
vector<int>V[N];
int Ls(int x){return lower_bound(t+,t++T,x)-t;}
int Rl(int x){return t[x];}
void adde(int u,int v)
{
//printf("adde : %d %d\n",u,v);
V[u].push_back(v);
V[v].push_back(u);
du[u]++; du[v]++;
}
void del(int u,int v)
{
//printf("del %d %d\n",u,v);
for (int i=;i<V[u].size();++i)
if (V[u][i]==v) {
V[u].erase(V[u].begin()+i);
break;
}
for (int i=;i<V[v].size();++i)
if (V[v][i]==u) {
V[v].erase(V[v].begin()+i);
break;
}
}
void dfs(int u)
{
//printf("u = %d \n",u);
for (int i=;i<V[u].size();++i) {
int v=V[u][i]; del(u,v); dfs(v);
}
Path[++Path[]]=u;
}
int main()
{
scanf("%d",&n);
for (int i=;i<=n-;i++) scanf("%d",&a[i]),t[++t[]]=a[i];
for (int i=;i<=n-;i++) scanf("%d",&b[i]),t[++t[]]=b[i];
for (int i=;i<=n-;i++)
if (a[i]>b[i]) { puts("-1"); return ;}
sort(t+,t++t[]);
T=unique(t+,t++t[])-t-;
for (int i=;i<=n-;i++)
adde(Ls(a[i]),Ls(b[i]));
bool flag=false; int cnt=;
for (int i=;i<=n;i++)
if (du[i]%==) cnt++;
if (cnt!=&&cnt!=) { puts("-1"); return ;}
for (int i=;i<=n;i++)
if (du[i]%==) { flag=true; dfs(i); break;}
if (flag==false) dfs();
if (Path[]!=n) { puts("-1"); return ; }
for (int i=;i<=Path[];i++)
printf("%d ",Rl(Path[i]));
puts("");
return ;
}

E.cpp

Codeforces Round #554 ( div.2 ) 总结的更多相关文章

  1. Codeforces Round #554 (Div. 2) C. Neko does Maths (简单推导)

    题目:http://codeforces.com/contest/1152/problem/C 题意:给你a,b, 你可以找任意一个k     算出a+k,b+k的最小公倍数,让最小公倍数尽量小,求出 ...

  2. Codeforces Round #554 (Div. 2) 1152B. Neko Performs Cat Furrier Transform

    学了这么久,来打一次CF看看自己学的怎么样吧 too young too simple 1152B. Neko Performs Cat Furrier Transform 题目链接:"ht ...

  3. Codeforces Round #554 (Div. 2) 1152A - Neko Finds Grapes

    学了这么久,来打一次CF看看自己学的怎么样吧 too young too simple 1152A - Neko Finds Grapes 题目链接:"https://codeforces. ...

  4. Codeforces Round #554 (Div. 2)-C(gcd应用)

    题目链接:https://codeforces.com/contest/1152/problem/C 题意:给定a,b(<1e9).求使得lcm(a+k,b+k)最小的k,若有多个k,求最小的k ...

  5. Codeforces Round #554 (Div. 2) D 贪心 + 记忆化搜索

    https://codeforces.com/contest/1152/problem/D 题意 给你一个n代表合法括号序列的长度一半,一颗有所有合法括号序列构成的字典树上,选择最大的边集,边集的边没 ...

  6. Codeforces Round #554 (Div. 2) C 数论

    https://codeforces.com/contest/1152/problem/C 题意 a和b,找到k,使得lcm(a+k,b+k)最小(a,b:1e9) 题解 设gcd=gcd(a+k,b ...

  7. Codeforces Round #554 (Div. 2) C.Neko does Maths (gcd的运用)

    题目链接:https://codeforces.com/contest/1152/problem/C 题目大意:给定两个正整数a,b,其中(1<=a,b<=1e9),求一个正整数k(0&l ...

  8. CodeForces Round #554 Div.2

    A. Neko Finds Grapes 代码: #include <bits/stdc++.h> using namespace std; ; int N, M; int a[maxn] ...

  9. Codeforces Round #554 (Div. 2)自闭记

    A 签到 #include<bits/stdc++.h> using namespace std; ],t[],ans; int main() { scanf("%d%d&quo ...

  10. Codeforces Round #554 (Div. 2) C. Neko does Maths(数学+GCD)

    传送门 题意: 给出两个整数a,b: 求解使得LCM(a+k,b+k)最小的k,如果有多个k使得LCM()最小,输出最小的k: 思路: 刚开始推了好半天公式,一顿xjb乱操作: 后来,看了一下题解,看 ...

随机推荐

  1. 05Hadoop 概论

    Hadoop的思想之源:Google Google搜索引擎,Gmail,安卓,AppspotGoogle Maps,Google earth,Google 学术,Google翻译,Google+,下一 ...

  2. fileInput插件上传文件

    一.ftl <form action="" method="post" name="form" id="form" ...

  3. Jenkins [Error] at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.redeploy(AbstractTomcatManagerDeployer.java:192)

    Deploying /root/.jenkins/workspace/zgg-crm-pre/target/crm.war to container Tomcat 7.x Remote with co ...

  4. [转帖]mimikatz 学习

    mimikatz mimikatz 2.0 vient de sortir en version alpha binaires : https://github.com/gentilkiwi/mimi ...

  5. Oracle数值函数

    --数值函数 --四舍五入 ) from dual ) from dual --数字截取 ) from dual --取模 ,) from dual

  6. 谈谈B-树和B+树及其应用

    待更!!! B-树和B+树的应用:数据搜索和数据库索引 B+/-Tree原理及mysql的索引分析 从B树.B+树.B*树谈到R 树 B树.B-树.B+树.B*树

  7. drf实现图片验证码功能

    一.背景 在之前实现过django的图片验证码,有自己实现过的,也有基于django-simple-captcha的,都是基于form表单验证,若自己实现,可以获取相应的标签name便可以获取判断,若 ...

  8. linux audit审计(7-1)--读懂audit日志

     auid=0 auid记录Audit user ID,that is the loginuid.当我使用lbh用户登录系统时,再访问audit_test,此时记录的auid为1001,具体日志如下: ...

  9. ansible的playbook简单使用

    一.介绍 playbook就是一个用yaml语法把多个模块堆起来的一个文件 核心组件: Hosts:执行的远程主机列表Tasks:任务,由模块定义的操作的列表:Varniables:内置变量或自定义变 ...

  10. python3 写的一个压测脚本(有待开发)

    import requests import queue import threading import time status_code_list = [] exec_time = 0 class ...