应该经常需要锻炼一下英语阅读理解能力和代码能力,所以以后还是需要多打打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

最新文章

  1. 统计文件种类数+获取子shell返回值的其它方法
  2. Redis中的简单事物以及消息订阅发布
  3. 黑马程序员——JAVA基础之标准输入输出流
  4. 如何实现ZBrush 4R7中按钮颜色的自定义
  5. cas+tomcat+shiro实现单点登录-2-部署cas server到tomcat
  6. C# 模拟提交带附件(input type=file)的表单
  7. UVA 11292 - The Dragon of Loowater (water)
  8. Android监听WebView滑动到底部
  9. pku 1330 Nearest Common Ancestors LCA离线
  10. curl支持HTTP和https
  11. Docker快速配置指南
  12. EBS中内部银行相关API
  13. python使用正则解析网络地址的各个部分
  14. 微信小程序发布新版本时自动提示用户更新
  15. 建议2---编写pythonic代码
  16. [Luogu 3787] 冰精冻西瓜
  17. 27. Remove Element C++移除元素
  18. 【转】mysql给root开启远程访问权限,修改root密码
  19. APP中https证书有效性验证引发安全问题(例Fiddler可抓https包)
  20. 通过 Spark R 操作 Hive

热门文章

  1. React Native之本地文件系统访问组件react-native-fs的介绍与使用
  2. 《Effective C++》设计与声明:条款18-条款25
  3. Oracle pivot行转列函数案例
  4. python爬虫之scrapy模拟登录
  5. mysql 分库分表备份脚本
  6. Kettle转换工具Windows版安装
  7. IWMS后台上传文章,嵌入音频文件代码
  8. Ubuntu16.04网络不能访问解决办法
  9. Spring Boot 构建电商基础秒杀项目 (八) 商品创建
  10. Mayor&#39;s posters(线段树+离散化)