XDFZOI 月赛 201905 Sliver
组题人自己组完过后,才发现自己还是太弱了。。。
T1
简单模拟。
按照游戏规则直接模拟显然是不明智的,所以我们可以像石头剪刀布一样,将判断改变为检验。
同时,我们发现,一共只有48种牌,所以我们可以直接开一个数组记录一下,\(card[peo][col][tag]\)表示第\(peo\)个人,第\(col\)种颜色,第\(tag\)种牌型有多少张
然后,按照优先级,暴力枚举每个人的每一张牌,同时根据游戏规则进行检验,比如当此时仍有"+2"卡在传递时,除了"+2"和"turn"两种牌型牌型外其余任何牌型都不能出等等。
然后这个题目就解决啦!
Upd:有点锅,按照题意修改了一下题面(是我没表述清楚啦QAQ)
#include<bits/stdc++.h>
using namespace std;
int card[20][20][20];
int cnt[10],vis[10];
struct cc{
int lei,tim,id;
}boom[10];
bool cmp(cc x,cc y)
{
return x.lei==y.lei?x.tim<y.tim:x.lei<y.lei;
}
bool check(int col,int tag,int lstcol,int lsttag,int dl)
{
if(lstcol==-1&&lsttag==-1) return 1;
if(dl)
{
if((col==lstcol)&&(tag==12||tag==11)) return 1;
return 0;
}
else
{
if(col==lstcol||(tag==lsttag&&tag!=11&&tag!=12)) return 1;
else return 0;
}
}
int main()
{
// freopen("UnIon10.in","r",stdin);
// freopen("UnIon10.out","w",stdout);
// freopen("样例解释.out","w",stdout);
int ggg=0;
for(int i=1;i<=4;++i)
{
scanf("%d",&cnt[i]),boom[i].id=i,ggg+=cnt[i];
}
for(int i=1;i<=4;++i)
{
for(int j=1;j<=cnt[i];++j)
{
int a,b;
scanf("%d%d",&a,&b);
++card[i][a][b];
}
}
int nex=1,now=1,peo=4,dilei=0,lc=-1,lt=-1;
int ti=0;
if(!ggg)
{
printf("0 0 0 0 \nxiaoai\n");
return 0;
}
while(peo>1)
{
// printf("%d\n",peo);
if(now==0) now=4;
if(now==5) now=1;
int flag=0;
if(!cnt[now])
{
now+=nex;
continue;
}
vis[now]=1;
++ti;
for(int i=1;i<=4;++i)
{
for(int j=12;j>=1;--j)
{
if(card[now][i][j]&&check(i,j,lc,lt,dilei))
{
flag=1;
// printf("%d %d %d\n",now,i,j);
--card[now][i][j];
--cnt[now];
lc=i;
lt=j;
if(j==12) nex=-nex;
if(j==11) dilei+=2;
break;
}
}
if(flag) break;
}
if(!cnt[now]) --peo,boom[now].tim=ti;
if(!flag) ++boom[now].lei,lc=-1,lt=-1,boom[now].lei+=dilei,dilei=0;
now+=nex;
}
while(!cnt[now])
{
now+=nex;
if(now==0) now=4;
if(now==5) now=1;
}
boom[now].lei+=dilei;
for(int i=1;i<=4;++i)
boom[i].lei+=cnt[i],printf("%d ",boom[i].lei);
sort(boom+1,boom+5,cmp);
printf("\n");
if(boom[1].id==1) puts("xiaoai");
else if(boom[1].id==2) puts("Yoyo");
else if(boom[1].id==3) puts("Siri");
else if(boom[1].id==4) puts("Bixby");
return 0;
}
T2
这是一道二合一的题目。
简单二分 (三分)+简单背包
首先,只要你学过背包就一定能看出这是一个背包问题,还是一个放满背包问题。
在这里就不细说了,简单讲一讲前面的部分
求
\]
已知\(f(x)\),求较小的\(x\)
首先,我们可以将这个函数的图像画出来 比赛时这么做的打死

可以很清晰的看到在这个函数当中有一个最低点,跟二次函数类似。
那,怎样求最低点呢?
标准解法:三分法
可以右转洛谷模板区
对于一个在\([l,r]\)区间上存在最值的函数\(f(x)\),都可以用三分法解决。

观察这张图,就可以轻松找到规律(转载声明,感谢图片)
1、当 f(mid) > f(mmid) mmid 一定在白点的右边。
2、当 f(mid) < f(mmid) mid 一定在白点的左边。
然后就可以愉快的三分了
非标准解法:枚举法
我们将函数图像进一步放大,或者也可以通过函数有关的知识可以得到,这个最低点一定在01之间,所以,题目要求保留5位小数,我们可以枚举67位小数,取其中得到的最小值,同样可以得到答案。
找到最低点之后,我们发现,在最低点左边的部分单调,在最低点右边的部分也单调,所以我们可以采取分段二分的方式,针对不同的数据范围,进行方向调整不同的二分,就可以求出每个小面包所需要的最低成本,然后以其为价值,进行dp即可。
于是这道题目也被解决了。
#include<bits/stdc++.h>
#define eps 1e-9
#define low 0.36787897
using namespace std;
const int maxn=200000;
int n;
long double l,r=20;
double fff(double x){return pow(x,x);}
double solve(double x)
{
l=0,r=20;
if(x<1)
{
r=low;
while(r-l>eps)
{
double mid=(l+r)/2.0;
if(fff(mid)>x) l=mid;
else r=mid;
}
return l;
}
else
{
l=low;
while(r-l>eps)
{
double mid=(l+r)/2.0;
if(fff(mid)<x) l=mid;
else r=mid;
}
return l;
}
}
int c[maxn];
double v[maxn],f[maxn];
int opt;
int main()
{
freopen("baker.in","r",stdin);
freopen("baker.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%lf%d",&v[i],&c[i]),v[i]=solve(v[i]);
for(int i=1;i<=20000;++i)
f[i]=(double)998244353;
f[0]=0;
for(int i=1;i<=n;++i)
for(int j=c[i];j<=20000;++j)
f[j]=min(f[j],f[j-c[i]]+v[i]);
for(int i=1;i<=m;++i)
{
scanf("%d",&opt);
while(f[opt]==998244353&&opt>0) --opt;
if(opt==0) printf("-1T^T1-\n");
else printf("%d %.5lf\n",opt,f[opt]);
}
return 0;
}
T3
老实说,这是我扒的原题,因为解法太多,也有值得借鉴的地方,就搬过来了。
简化版题意:求一个区间内的众数,且出现次数在区间中超过区间长度的一半。
首先,因为我是分块讲课人,自然要让大家学以致用。
使用分块,可以得到80%左右的分数,因为空间开不下,时间也不够。
使用莫队,可以得到86分,剩下14分,被我卡掉了。
开不开心,激不激动?
首先介绍一个知识
摩尔投票法
非常通俗的说,两群人打架,里面每个人都属于某一个帮派,现在两两PK,若是同一个帮派则握手平局,否则便两人皆淘汰。这样的话,很自然的可以得出,只要某一个帮派人数超过了总人数的1/2,就可以赢得比赛胜利。
摩尔投票法就是这样一个思想。
由于作者时间所限,给出题目链接:
利用这种方法,可以轻松通过m=1的数据。
下面抛出一个问题,摩尔投票法具有可加性吗?
答案是肯定的。
那我们可以用什么进行维护呢?
当然是线段树辣!!
这个东西,我们在后面会进一步提到。
但是,用线段树维护并不能保证找到的一定是正确的解。
所以我们需要对每一个数字开一个vector,记录其位置,然后检验一下,不成功就输出0
时间复杂度为\(O(nlogn)\)
记得我在讲搜索的时候,讲了一种剪枝方法——随机化剪枝,从此很多人就走上了不归路。
更进一步
既然维护了线段树都需要检验,可不可以不维护,直接进行检验呢?
我们先来解决这样一个数学问题:一个口袋里10个球,5红,5蓝,连续摸n次(放回),一次都摸不到红球的概率是?
显然,答案为\(1/2^{n}\)
那么,是不是,只要n足够大,就可以看作一定能摸到呢?
对于本题来说,可以,如果你的n到达到了20,就已经超出了这个范围,可以看作无错。
于是这个题目就解决啦!!
原题链接:P3567
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=6e5+10;
vector<int> pos[maxn];
int v[maxn];
bool vis[maxn];
int s[maxn],cnt;
int random(int x)
{
return 1ll*rand()*233%x;
}
int main()
{
// freopen("randerlng.in","r",stdin);
// freopen("randerlng.out","w",stdout);
srand(time(0));
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&v[i]),pos[v[i]].push_back(i);
for(int i=1;i<=m;++i)
{
int x,y,flag=1;
scanf("%d%d",&x,&y);
for(int j=1;j<=20;++j)
{
int now=v[x+random((y-x+1))];
if(vis[now]) continue;
vis[now]=1;
s[++cnt]=now;
if(pos[now].size()<=((y-x+1)/2)) continue;
int num=upper_bound(pos[now].begin(),pos[now].end(),y)-lower_bound(pos[now].begin(),pos[now].end(),x);
if(num>(y-x+1)/2)
{
printf("%d\n",now);
flag=0;
break;
}
}
while(cnt) vis[s[cnt]]=0,--cnt;
if(flag)
puts("0");
}
return 0;
}
拓展
按照作者的本意,本题还应该要支持修改操作(但是由于用现有知识复杂度不严格取消了),应该怎么办呢?
按照随机的做法,我们只需要将vector中的保存的位置删除再添加即可,但这样做是\(O(n)\)的。
于是我们需要用平衡树来解决这个问题。
具体见此题:P3765
于是这场比赛就完了。
总结
这场比赛还是太水啦
估计:每人至少150pts+?
下次一定会难一点的,毕竟地球还在流浪嘛(手动狗头)
XDFZOI 月赛 201905 Sliver的更多相关文章
- fzu月赛 2203 单纵大法好 二分
Accept: 8 Submit: 18Time Limit: 5000 mSec Memory Limit : 65536 KB Problem Description 人在做,天在看 ...
- FZU2138-久违的月赛之一
Problem Description 好久没举月赛了,这次lqw给大家出了5道题,因为hsy学长宣传的很到位,吸引了n个DDMM们来做,另一位kk学长说,全做对的要给金奖,做对4题要给银奖,做对3题 ...
- USACO月赛数据
终于找到了usaco月赛的数据…… 根据月赛的名称,我们可以写出数据地址.比如08年一月的月赛即是:http://contest.usaco.org/JAN08 这里要注意区分大小写.
- 月赛-Crackhash
Crackhash 这个题目是我为月赛出的,完全仿照自mma 1st simple_hash. 这道题目比较有意思的地方在于在32位的程序中模拟了64位的算术运算. 题目的思路很清晰.要求输入全为数字 ...
- USACO全部月赛及GateWay数据
月赛: 以07年open为例,网站如下 http://contest.usaco.org/OPEN07 其他的格式是http://contest.usaco.org/月份(月份的英文前三位,比如1月是 ...
- [BZOJ 4832][lydsy 4月赛] 抵制克苏恩
题面贴一发 [Lydsy2017年4月月赛]抵制克苏恩 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 443 Solved: 164[Submit][ ...
- [补档][Lydsy2017年4月月赛]抵制克苏恩
[Lydsy2017年4月月赛]抵制克苏恩 题目 小Q同学现在沉迷炉石传说不能自拔.他发现一张名为克苏恩的牌很不公平. 如果你不玩炉石传说,不必担心,小Q同学会告诉你所有相关的细节.炉石传说是这样的一 ...
- 洛谷4月月赛R2
洛谷4月月赛R2 打酱油... A.koishi的数学题 线性筛约数和就可以\(O(N)\)了... #include <iostream> #include <cstdio> ...
- 洛谷3月月赛 R1 Step! ZERO to ONE
洛谷3月月赛 R1 Step! ZERO to ONE 普及组难度 290.25/310滚粗 t1 10分的日语翻译题....太难了不会... t2 真·普及组.略 注意长为1的情况 #include ...
随机推荐
- Python+Selenium - 定位策略
一个元素定位可能会在多个地方用到,用loc变量接收元素的定位方式和相对路径.使用时再拆包(*loc) loc = (定位方式,'定位方式对应的元素路径') =>元素定位方式及路径 driv ...
- checkbox,select,radio 选取值,设定值,回显值
获取一组radio被选中项的值var item = $('input[@name=items][@checked]').val();获取select被选中项的文本var item = $(" ...
- JVM Ecosystem Report 2020 (2020年JVM生态系统报告)
本文翻译自SNYK于2020年发布的< JVM Ecosystem Report 2020 >,全文使用机器翻译自动生成,人为将翻译的离谱和翻译明显错误的地方修正到勉强能看懂的程度. 英语 ...
- 干货!MySQL 的 InnoDB 存储引擎是怎么设计的?
MySQL 里还有什么其他成员呢? 对于 MySQL,要记住.或者要放在你随时可以找到的地方的两张图,一张是 MySQL 架构图,另一张则是 InnoDB 架构图: 遇到问题,或者学习到新知识点时,就 ...
- Luat Inside | 致敬经典,使用Air724UG制作简易贪吃蛇
作者简介: 打盹的消防车--活跃于Luat社群的新生代全能开发者,东北小伙儿爽朗幽默.好学敏思,更是实力行动派.幼年曾手握火红炽铁而后全然无恙,堪称魔幻经历:如今热衷于各类嵌入式软硬件研究,快意物联江 ...
- Java-学习日记(Java8异步)
今天用到的中异步操作:异步编程与异步处理数据 //里面返回其他接口服务使用CompletableFuture CompletableFuture.runAsync(()->{ driverNoR ...
- 一次性讲清楚spring中bean的生命周期之一:getSingleton方法
要想讲清楚spring中bean的生命周期,真的是不容易,以AnnotationConfigApplicationContext上下文为基础来讲解bean的生命周期,AnnotationConfigA ...
- Task异常捕获的方式
这节来讲一下如果捕获Task的异常. 当Task运行中出现了异常,正常情况下我们在主线程的Try是捕获不到的,而如果在Task内部写try,出现了异常我们会完全不知道.下面就来介绍几个主线程捕获Tas ...
- ES6学习笔记之字符串新增方法
1.字符串的子串识别 传统上,Javascript 只有indexof 方法,用来确定一个字符串是否包含在另一个字符串中.如: //indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的 ...
- 13、ssh跳板机
13.1.前提条件: 1.跳板机服务器和其它服务器建立了ssh秘钥登录: 2.目前的环境: (1)各服务器上都建立了lc用户,并给于sudo (lc ALL= NOPASSWD:ALL )权限,lc就 ...