比赛链接:牛客小白月赛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. System.IO.FileSystemWatcher的坑

    System.IO命名空间下面有一个FileSystemWatcher,这个东西可以实现文件变动的提醒.需要监控文件夹变化(比如FTP服务器)的情形非常适用. 需要监控文件新建时,我们可以这么写: _ ...

  2. 鼠标悬浮上去显示小手CSS

    鼠标悬浮上去显示小手CSS只需要添加一句css代码即可 cursor:pointer;

  3. 关于 Vue 中 h() 函数的一些东西

    最近在项目上需要一个信息弹窗,来显示信息.一开始只让它弹出了文字,而且只有一条信息.而给我的需求是多条文字和图片,而后我使用了element ui中的 Notification 通知组件来显示.当然, ...

  4. 1.轮询、长轮询、websocket简介

    一.轮询 前端每隔固定时间向后台发送一次请求,询问服务器是否有新数据   缺点: 延迟,需要固定的轮询时间,不一定是实时数据 大量耗费服务器内存和宽带资源,因为不停的请求服务器,很多时候 并没有新的数 ...

  5. Python爬虫requests请求库

    requests:pip install  request 安装 实例: import requestsurl = 'http://www.baidu.com'response = requests. ...

  6. HTTP(s) API 经验总结

    目录 参考文章 First URL HTTP(s)-Header 请求方式 参考文章 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overvie ...

  7. Day2.1

    HelloWorld 随便新建一个文件夹,存放代码 新建一个java文件 文件后缀名为.java Hello.java 注意:系统可能没有显示文件名后缀,我们需要手动打开 编写代码 public cl ...

  8. SpringBoot 自动装配原理

    早期的Spring项目需要添加需要配置繁琐的xml,比如MVC.事务.数据库连接等繁琐的配置.Spring Boot的出现就无需这些繁琐的配置,因为Spring Boot基于约定大于配置的理念,在项目 ...

  9. vue3的学习笔记:MVC、Vue3概要、模板、数据绑定、用Vue3 + element ui、react框架实现购物车案例

    一.前端MVC概要 1.1.库与框架的区别 框架是一个软件的半成品,在全局范围内给了大的约束.库是工具,在单点上给我们提供功能.框架是依赖库的.Vue是框架而jQuery则是库. 1.2.MVC(Mo ...

  10. Ansible执⾏速度优化

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying 优化⼀: 开启SSH长连接 Ansible模式是使⽤SSH和远程主机进⾏通信, 所以Ansi ...