比赛链接:牛客小白月赛65_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

A:牛牛去购物

题意:

给n元钱,有两种商品,价格为a和b,问最少能花到剩多少钱?

思路:

一开始就猜了发结论:min({n % a,n % b,n % a % b,n % b % a})

感觉自己对麻了

然后喜提WA

但是实际上要花到最少并不一定是先把其中一个花到不能再花才考虑另外一个

比如一个反例就是n = 33,a = 4,b = 7

先买a,买到剩1元,就啥都买不了了

先买b,买到剩5元,再买a,买到剩1元

实际上最优解是先买三个a,剩21元,再买3个b,剩0元

看看数据范围都是<=1000的,直接暴力就完事了

第一重循环枚举买a的数量[0,n / a]

第二重循环枚举买b的数量[0,n / a]

判断条件是i * a + j * b <= n

然后一直取min就完事了

代码:

void solve()
{
int ans = 1e18;
int a,b;
cin >> n >> a >> b;
for(int i = 0;i <= n / a;i++)
{
for(int j = 0;j <= n / b;j++)
{
if(i * a + j * b <= n)
{
ans = min(ans,n - i * a - j * b);
}
}
}
cout << ans << endl;
}

总结:

看看数据范围再决定猜结论还是打暴力(

如果能打暴力坚决不猜结论!

B:牛牛写情书

题意:

给一个长度为n的初始字符串和一个长度为m的目标字符串

问初始字符串去掉除开小写字母以外的字符后是否含有目标字符串

思路:

思路很显然,模拟即可

就先用个字符串收集初始字符串中的小写字母

然后再用一下find()函数来判断即可

代码:

void solve()
{
string s1,s2,s3;
cin >> n >> m;
cin >> s1 >> s2;
for(int i = 0;i < n;i++)
{
if(s1[i] >= 'a'&&s1[i] <= 'z') s3 += s1[i];
}
if(s3.find(s2) != -1) YES;
else NO;
}

总结:

A题卡了可以先看看后面的,感觉B比A简单一些(

C:牛牛排队伍

题意:

有一个1到n的排列

有m次操作和询问

操作是去掉排列的某个数字

询问是输出某个数字的前面一个数字,如果这个数字是第一个数字就输出0

思路:

按要求模拟即可

因为涉及到去除数字和查找数字

我选择用set来模拟

查找数字用find()即可

去除数字用erase()即可

代码:

void solve()
{
cin >> n >> m;
set<int> s;
for(int i = 1;i <= n;i++) s.insert(i);
int x,y;
while(m--)
{
cin >> x >> y;
if(x == 1) s.erase(y);
else
{
auto it = s.find(y);
if(it == s.begin()) cout << 0 << endl;
else cout << *prev(it) << endl;
}
}
}

C题总结:

STL容器和函数还是很有用的!

D题:牛牛取石子

题意:

给两堆石子为n和m,石子数为a和b

牛牛先手,牛妹后手

操作有两种

一种为在n堆取1个,m堆取2个

一种为在n堆取2个,m堆取1个

谁先无法取石子谁就输

思路:

最开始考虑先手必胜,咋个都想不出来

后来考虑后手必胜:

如果数量少的那一堆石子%3 == 0的话

不管牛牛咋个取石子

牛妹跟他弄相反的操作即可

这样牛妹是必胜的

反之,如果石子数 % 3 != 0

牛牛只要操作一次使得小的那一堆 % 3 == 0即可

显然这个结论是成立的

然后就喜提WA

如果两个数字是一样的捏

比如 4 4

这种牛牛就做不到必胜了

因为不管咋个操作都会变成 2 3

也就是说如果(两个数字一样的&&小的一堆 % 3 != 0) != 牛牛必胜

原因就是之前的证明都默认了第一次操作不会改变a,b的相对大小

所以这里再判断一下

如果两个数相等且石子数 % 3 == 2 -> 牛牛必胜

如果两个数相等且石子数 % 3 == 1 -> 牛妹必胜

代码:

void solve()
{
cin >> n >> m;
if(n > m) swap(n,m);
if(n % 3 == 0) cout << "niumei" << endl;
else if(n == m)
{
if(n % 3 == 1) cout << "niumei" << endl;
else cout << "niuniu" << endl;
}
else cout << "niuniu" << endl;
}

总结:

后来才知道这种叫做"对称博弈"

就是两种操作是对称的

一般对称博弈都是考虑后手必赢状态

因为后手只要对称着操作

两次操作就会某种形式上的抵消

决定是否抵消的是后手

当然先手也可以通过操作来使得下一次操作变成必输态

这就要根据题来讨论了

E:牛牛的构造

题意:

 
 
 
 
要你构造一个长度为n的排列,并且满足
这个排列恰好有k个二元组
二元组条件为:1 <= i < j <= n&&ai - aj = 2x

思路:

赛事没弄出来(实际根本没去想)

典型的构造题

典型的没思路

先想想极端情况

如果一个排列是从小到大的->0个二元组

如果排列是从大到小的捏

如果数字从n开始,那么后面满足的数字有这些:

n - 1,n - 2,n - 4,n - 8,n - 16.......

因为n - (n - x) = x

由于是个排列,换种方式考虑

n=6时:6 5 4 3 2 1

6 - 5 = 1,6 - 4 = 2,6 - 3 = 3,6 - 2 = 4,6 - 1 = 5

5 - 4 = 1,5 - 3 = 2,5 - 2 = 3,5 - 1 = 4;

......

发现就是对于一个逆序的排列

每个数算贡献的时候考虑的都是[1,p[i] - 1]

那么在[1,p[i] - 1]中的贡献为log2(p[i] - 1) + 1

公式就出来了

打个表:

2    3    4    5    6    7    8    9

1    2    2    3    3    3    3    4

所以如果要构造的n算出来的值如果小于了k

可以直接退出然后输出-1了(因为这已经是最大的情况了)

如果刚好等于k当然可以直接输出逆序的排列

然后就是关于这个值<k了

这题的结论就是如果这个值<k,不管是啥都可以构造出来

不会证明

然后最关键的地方来了((

要做这题就要想个构造方式

这题的构造方式就是:先降后升

比如要构造贡献为11的,n为9的

根据上面打的表

4 + 3 + 3 + 1即可

对应的就是9 8 7 2

然后加上剩余的数

就是9 8 7 2 1 3 4 5 6

可以发现:

对于前面降序的数有这个性质:比这个数小的都在这个数后面

那么可以直接通过上面那个表求出相应的值

而对于后面升序的数来说,已经和前面的数算过贡献,但是后面的数又都比当前位置的数大

所以后面的数贡献都是0

所以结论就是:

只要在算出的那个表中选出几个数字且这几个数之和为k作为前面降序的数就好了

我以为这里要用背包来着

结果从大到小贪心即可

不会证明

代码:

void solve()
{
cin >> n >> m;
if(n == 1)
{
if(m == 0) cout << 1 << endl;
else cout << -1 << endl;
return;
}
int sum = 0;
vector<int> a(n + 10),b(n + 10),st(n + 10);
for(int i = 1;i <= n;i++) a[i] = i;
for(int i = 2;i <= n;i++) b[i] = (int)log2(a[i] - 1) + 1,sum += b[i];
// cout << b[3] << endl;
reverse(all(a));
reverse(all(b));
// for(int i = 1;i <= n;i++) cout << a[i] << " ";
// cout << endl;
// for(int i = 1;i <= n;i++) cout << b[i] << " ";
// cout << endl;
if(sum < m) cout << -1 << endl;
else if(sum == m)
{
for(int i = 1;i <= n;i++) cout << a[i] << " ";
cout << endl;
}
else
{
int res = 0;
for(int i = 1;i <= n;i++)
{
if(res + b[i] <= m)
{
res += b[i];
st[i] = 1;
cout << a[i] << " ";
}
}
for(int i = n;i >= 1;i--)
{
if(!st[i]) cout << a[i] << " ";
}
}
}

总结:

这题感觉非常巧妙((

即使听了思路也是如此

对于这类构造题,先要去考虑一下极端情况,比如最多多少,最少多少

然后再根据极端情况来进行调整

然后再根据性质推出一些结论

但是这题的先降序后升序这里

感觉确实比较人类智慧((

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

牛客小白月赛65ABCD(E)的更多相关文章

  1. 树的最长链-POJ 1985 树的直径(最长链)+牛客小白月赛6-桃花

    求树直径的方法在此转载一下大佬们的分析: 可以随便选择一个点开始进行bfs或者dfs,从而找到离该点最远的那个点(可以证明,离树上任意一点最远的点一定是树的某条直径的两端点之一:树的直径:树上的最长简 ...

  2. 牛客网 牛客小白月赛5 I.区间 (interval)-线段树 or 差分数组?

    牛客小白月赛5 I.区间 (interval) 休闲的时候写的,但是写的心情有点挫,都是完全版线段树,我的一个队友直接就水过去了,为啥我的就超内存呢??? 试了一晚上,找出来了,多初始化了add标记数 ...

  3. 牛客小白月赛8 - E - 诡异数字 数位DP

    牛客小白月赛8 - E - 诡异数字 题意: 求区间中,满足限制条件的数字的个数. 限制条件就是某些数字不能连续出现几次. 思路: 比较裸的数位DP, DP数组开一个dp[len][x][cnt] 表 ...

  4. 牛客小白月赛18 Forsaken给学生分组

    牛客小白月赛18 Forsaken给学生分组 Forsaken给学生分组 链接:https://ac.nowcoder.com/acm/contest/1221/C来源:牛客网 ​ Forsaken有 ...

  5. 牛客小白月赛18 Forsaken喜欢数论

    牛客小白月赛18 Forsaken喜欢数论 题目传送门直接点标题 ​ Forsaken有一个有趣的数论函数.对于任意一个数xxx,f(x)f(x)f(x)会返回xxx的最小质因子.如果这个数没有最小质 ...

  6. 牛客小白月赛19 E 「火」烈火燎原 (思维,树)

    牛客小白月赛19 E 「火」烈火燎原 (思维,树) 链接:https://ac.nowcoder.com/acm/contest/2272/E来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空 ...

  7. 【牛客小白月赛21】NC201604 Audio

    [牛客小白月赛21]NC201604 Audio 题目链接 题目大意: 给出三点 ,求到三点距离相等的点 的坐标. 解析 考点:计算几何基础. 初中蒟蒻表示不会什么法向量.高斯消元..qwq 方法一: ...

  8. 【牛客小白月赛21】NC201605 Bits

    [牛客小白月赛21]NC201605 Bits 题目链接 题目描述 Nancy喜欢做游戏! 汉诺塔是一个神奇的游戏,神奇在哪里呢? 给出3根柱子,最开始时n个盘子按照大小被置于最左的柱子. 如果盘子数 ...

  9. 牛客小白月赛16 小石的妹子 二分 or 线段树

    牛客小白月赛16 这个题目我AC之后看了一下别人的题解,基本上都是线段树,不过二分也可以. 这个题目很自然就肯定要对其中一个进行排序,排完序之后再处理另外一边,另一边记得离散化. 怎么处理呢,你仔细想 ...

  10. 牛客小白月赛6 E 对弈 思维

    链接:https://www.nowcoder.com/acm/contest/136/E来源:牛客网 题目描述 善弈者谋势,不善弈者谋子.                               ...

随机推荐

  1. Python凯撒密码加解密

    #凯撒密码第一个版本 #加密 pxpt=input("请输入明文文本:") for p in pxpt: if 'a'<=p<='z': print(chr(ord(' ...

  2. 京东云TiDB SQL优化的最佳实践

    京东云TiDB SQL层的背景介绍 从总体上概括 TiDB 和 MySQL 兼容策略,如下表: SQL层的架构 用户的 SQL 请求会直接或者通过 Load Balancer 发送到 京东云TiDB ...

  3. abstract关键字的使用

    1.abstract:抽象的 2.abstract可以用来修饰的结构:类.方法 3.abstract修饰类:抽象类 此类不能实例化 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全 ...

  4. 在vue页面引入echarts,图表的数据来自数据库 springboot+mybatis+vue+elementui+echarts实现图表的制作

    文章目录 1.实现的效果 2.前端代码 3.后端controller代码 4.servie层代码 5.serviceImpl层代码 6.mapper层代码 7.xml中的sql语句 8.遇到的问题 8 ...

  5. VScode将代码提交到远程服务器、同时解决每次提交都要输入密码的问题(这里以gitee为例子)

    文章目录 1.第一种情况.项目直接从gitee上拉取下来 2.第二种情况.将新建的项目提交到远程服务器 3.解决将代码提交到远程每次都要输入用户名和密码 4.个人遇到的奇葩问题 1.第一种情况.项目直 ...

  6. 齐博x1换服务器如何转移网站?

    如果你要把网站从本机传到服务器,又或者要更换服务器,请按下面的操作处理 第一步,必须要在原网站后台备份数据. 第二步,把备份好的网站所有文件,传到新服务器或空间 特别要注意 \cache\ 目录下建议 ...

  7. 【ps下载与安装】Adobe Photoshop 2022 for Mac v23.5 中文永久版下载 Ps图像编辑软件

    Adobe Photoshop 2022 mac破解版,是一款Ps图像编辑软件,同时支持M1/M2芯片和Intel芯片安装,此主要的更新包括多个新增和改进的功能,例如改进的对象选择工具,其悬停功能可预 ...

  8. JavaScript实现带省略号的分页

    1.实现功能 可以跳转上一页.下一页.数据过多省略号显示,点击省略号可以实现快速跳转. 纯js+html+css实现,引入js文件后再使用方法即可快速生成. 2.实现过程 2.1 html页面(ind ...

  9. 2022春每日一题:Day 39

    题目:[USACO1.4]等差数列 Arithmetic Progressions 一个很显然的做法,枚举公差,首项,p,q这样的话复杂度爆炸,不过可以肯定的一点,如果我们这样做,找到了答案就可以直接 ...

  10. Containerd 如何配置 Proxy?

    前言 在某些 air gap 场景中,往往需要离线或使用代理 (Proxy), 例如: 需要通过 Proxy pull 容器镜像: Docker Hub: docker.io Quay: quay.i ...