The Preliminary Contest for ICPC Asia Xuzhou 2019
A:Who is better?
题目链接:https://nanti.jisuanke.com/t/41383
题意:
类似于有N个石子,先手第一次不能拿完,每次后手只能拿 1 到 前一次拿的数量*2之间的数量,不能拿时则输
分析:
最近一直在刷博弈论的题,比赛的前一天晚上打的华东师范校赛第一题也刚好是道博弈题,说起来两者还是有点类似的地方
但是这题显然要难的多,好在我打完华东师范校赛的我又狠狠的把博弈论专题看了一遍,也很巧的看到了这两篇博客
https://blog.csdn.net/dgq8211/article/details/7602807
https://blog.csdn.net/iteye_6233/article/details/82396581
所以推导的时候就留意了斐波那契博弈...
有涉及到取模不用说exgcd往里丢就完事,找到前几个答案后再把规律扔到http://oeis.org/
很快发现当N为斐波那契数的时候先手是必输的
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
#define mm(a,n) memset(a, n, sizeof(a))
using namespace std;
#define ll long long
template <class T>
void read(T &x)
{
x = ;
char ch = getchar();
while (!isdigit(ch))
ch = getchar();
while (isdigit(ch))
x = x * + ch - '', ch = getchar();
}
const int N = 1e3 + ;
ll a[N], m[N];
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = , y = ;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll z = x;
x = y;
y = z - y * (a / b);
return d;
}
ll winner(int n, ll *ans, ll *m)
{
ll a, b, c, d, x, y, t;
for (int i = ; i < n; i++)
{
a = m[i - ], b = m[i];
c = ans[i] - ans[i - ];
d = exgcd(a, b, x, y);
if (c % d)
return -;
t = b / d;
x = (x * (c / d) % t + t) % t;
ans[i] = ans[i - ] + m[i - ] * x;
m[i] = m[i] / d * m[i - ];
}
return ans[n - ];
}
map<ll,ll>haha;
int main()
{
ios::sync_with_stdio(false);
haha.clear();
haha[] = haha[] = ;
for(int i = ; i < ; ++i) haha[i] = haha[i-]+haha[i-];
int n;
read(n);
for (int i = ; i < n; i++)
{
read(m[i]);
read(a[i]);
}
ll ans = winner(n, a, m); if (ans == -)
cout << "Tankernb!" << endl;
else
{ int flag = ;
for(int i=; i<; i++)
{
if(haha[i] == ans)
flag = ;
}
if(flag)
cout << "Lbnb!" << endl;
else
cout << "Zgxnb!" << endl;
}
return ;
}
B:so easy
题目链接:https://nanti.jisuanke.com/t/41384
题意:
对于每次操作如果a是1则删除b,如果a是2则输出第一个大于等于b的数
分析:
我的水平真是对不起B题的题名
本来的想法是开个map——对于没有删除的数它对应的key值就为初始值0,对于删除的数它对应的初始值为1
然后对于key值为0的数直接输出即可,对于key值为1的数用二分找到第一个大于等于它的、且key值为0的数
然而map只是用来保存状态因此无法直接调用stl自带的二分,and手写的二分又各种bug,所以就很无奈的卡了一会
后来思索了一会想到题目的询问次数q<=1e6, 那么涉及到的数最多也只有1e6个,所以直接将所有读入的数保存+离散搞了一波
却很尴尬的WA了(这时候内心已经崩溃了)。 紧接着开始观察代码,因为比较长看得很晕,就索性认为是数据的储存出问题了
于是把所有数都输出来后,突然意识到二分只会对数组里的数进行操作,但是对于每个读入的数x,如果x已经被删除,那么我们
需要寻找的就是x的下一位数也就是x+1。
而仔细观察我们会发现每一次读入一个数XX的时候我们只要记录下XX+1,那么当下次我们要删除XX+1的时候,XX+2也会存在(读入的时候就会储存了)
于是我们查询第一个大于等于XX的时候要么答案为XX , 要么为XX+2(XX+1已被删除),这样就能保证题意
同理如果接来下我们要删除XX+2,那么在我们删除XX+2之前我们已将XX+3存入数组中,所以二分查找时就能找到XX+3
这道题还涉及到并查集的维护,这个操作也偏简单,就是维护XX的下一个空位(存在于数组中且未被删除)
#include<bits/stdc++.h>
#define numm ch - 48
using namespace std;
template <typename T>
void read(T &res)
{
bool flag = false;
char ch;
while (!isdigit(ch = getchar()))
(ch == '-') && (flag = true);
for (res = numm; isdigit(ch = getchar()); res = (res << ) + (res << ) + numm)
;
flag && (res = -res);
}
template <typename T>
void Out(T x)
{
if (x < )
putchar('-'), x = -x;
if (x > )
Out(x / );
putchar(x % + '');
}
const int N = 1e6 + ;
int a[N][];
int ans[N * ];
int father[N * ], cnt;
int find(int v)
{
return father[v] == v ? v : father[v] = find(father[v]);
}
int main()
{
int fuck, n, q, cot = , x;
read(n);
read(q);
for (int i = ; i <= q; i++)
{
read(fuck), read(x);
ans[++cot] = x - ;
ans[++cot] = x + ;
ans[++cot] = x;
a[i][] = fuck, a[i][] = x;
}
sort(ans + , ans + + cot);
int tot = unique(ans + , ans + + cot) - ans - ;
for (int i = ; i <= tot + ; i++)
father[i] = i;
for (int i = ; i <= q; i++)
{
if (a[i][] == )
{
int now = lower_bound(ans + , ans + + tot, a[i][]) - ans;
int u = find(now);
int v = find(now + );
father[u] = v;
}
else
{
int now = lower_bound(ans + , ans + + tot, a[i][]) - ans;
int u = find(now);
Out(ans[u]);
printf("\n");
}
}
return ;
}
赛后看了网上大佬的官方正解(unordered_map),再次为自己的菜感到自卑
老早前我就有在看关于hash表、hash函数的博客,虽然看懂了它的原理和储存方式,但却不知道具体代码实现的意义
今天特地问了一下大佬,这才知道unordered_map 其实和map差不多,简单讲一下区别:map和set差不多都有内置红黑树,就会自动按key值按字典序从小到大排序 而unordered_map 是采用了哈希函数,没有了排序功能,但是强大的点我们甚至可以用常数的时间进行查找的功能,最坏情况下也才是O(n) 而map的话因为排序了起步都是O(nlogn)
感觉收获还是蛮大的,下面贴下大佬的代码
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> mp;
int n,m;
int find_pre(int x){
if(!mp.count(x)) return x;
return mp[x]=find_pre(mp[x]);
}
int main(){
scanf("%d %d",&n,&m);
int op,x;
while(m--){
scanf("%d %d",&op,&x);
if(op==)
mp[x]=find_pre(x+);
else{
x=find_pre(x);
if(x>n) printf("-1\n");
else printf("%d\n",x);
}
}
return ;
}
日后还是要深入学习一下
C. Buy Watermelon
题目链接:https://nanti.jisuanke.com/t/41385
题意:
将一个西瓜切成两半后再判断每半西瓜的重量是不是2的倍数
分析:
很无脑的签到题,直接判断N是不是偶数,再判断N是否>2即可
#include <iostream>
#include <cstring>
#include <stack>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int w,flag=;
cin>>w;
if(w>&&w%==)
cout<<"YES\n";
else
cout<<"NO\n";
return ;
}
D. Carneginon
题目链接:https://nanti.jisuanke.com/t/41386
题意:略
分析:
也是一道痕无脑的签到题,唯一恶心的点就是题目太长
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
#define mm(a,n) memset(a, n, sizeof(a))
using namespace std;
#define ll long long
template <class T>
void read(T &x)
{
x = ;
char ch = getchar();
while (!isdigit(ch))
ch = getchar();
while (isdigit(ch))
x = x * + ch - '', ch = getchar();
}
const int N = 1e3 + ;
int main()
{
string T;
string S;
cin>>T;
int n;
cin>>n;
int len1=T.size();
while(n--)
{
cin>>S;
int len2=S.size();
if(len1>len2)
{
if(strstr(T.c_str(),S.c_str()))
{
cout<<"my child!"<<endl;
}
else
cout<<"oh, child!"<<endl;
}
else if(len1<len2)
{
if(strstr(S.c_str(),T.c_str()))
{
cout<<"my teacher!"<<endl;
}
else
cout<<"senior!"<<endl;
}
else
{
if(T==S)
{
cout<<"jntm!"<<endl;
}
else
cout<<"friend!"<<endl;
}
}
return ;
}
E. XKC's basketball team
题目链接:https://nanti.jisuanke.com/t/41387
题意:
给你n个数字,寻找第i个数字后面比i大至少m且距离i最远的数字
分析:
这道题头都快给队友搞晕了
读完题后感觉问题相对来说还是偏简单,a的人也偏多,我就交给队友划个水转手去干B题了
然而等我 Accpet 完B题后已经过了很久然而队友还是没有给我答应,于是心态崩了 ,感觉自
己不止这一场而是最近几场都是一个人在战斗 , 所以最后也没有等时间结束就直接离场吃饭
去了。晚上去教室学习的时候看了下题解和大佬们的代码,基本上都和单调栈/队列 + 二分 、 线段树维护最大区间值 + 二分 离不开关系
然而队友隔了很久只给我发了一个双重for循环0优化的暴力,也是有点莫名其妙,感觉以后这种题还是得自己来,队友有点靠不住
暑期集训的线段树专题好像也有类似题型 , 斟酌了一会后提交一发过
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
#define mm(a,n) memset(a, n, sizeof(a))
using namespace std;
#define ll long long
template <class T>
void read(T &x)
{
x = ;
char ch = getchar();
while (!isdigit(ch))
ch = getchar();
while (isdigit(ch))
x = x * + ch - '', ch = getchar();
}
const int N=5e5+; struct node
{
int l,r,MAX;
}tree[N<<]; int n,m;
int a[N]; void build(int i,int l,int r)
{
tree[i].l=l,tree[i].r=r;
if(l==r)
{
scanf("%d",&tree[i].MAX);
a[l]=tree[i].MAX;
return ;
}
int mid=l+r>>;
build(i<<,l,mid);
build(i<<|,mid+,r);
tree[i].MAX=max(tree[i<<].MAX,tree[i<<|].MAX);
} int query(int i,int l,int r,int v)
{
if(tree[i].l==tree[i].r)
return tree[i].l;
int mid=tree[i].l+tree[i].r>>;
if(tree[i<<|].MAX>=v)
return query(i<<|,l,r,v);
else if(l<=mid&&tree[i<<].MAX>=v)
return query(i<<,l,r,v);
else
return -;
} int main()
{
ios::sync_with_stdio(false);
read(n);read(m);
build(,,n);
int ans;
for(int i=;i<=n;i++)
{
if(i==n)
ans=-;
else
ans=query(,i+,n,a[i]+m);
if(ans!=-)
ans-=i+;
if(i == n)
cout<<ans<<endl;
else cout<<ans<<" ";
}
return ;
}
G. Colorful String
题目链接:https://nanti.jisuanke.com/t/41389
题意:
给定一个字符串,将该字符串的所有回文串的不重复出现的字母贡献记为1,计算总贡献值
分析:
真是晕了。。。
读完题目感觉是自己能A的题,因为不久前刚粗略的学习了一手回文自动机,然而并没有什么锤子用
思考了快一个小时又想着用马拉车算法搞一波 ,but很快发现想法是错的,于是最后就很尴尬的把时
间浪费在这道题身上
果然自己对字符串的处理还是远远不够的。
上次找涛哥教AC自动机也不知道他什么时候有空教,感觉他最近也挺忙的。。。
我想主要还是要是要我多自学点吧,加油加油加油
The Preliminary Contest for ICPC Asia Xuzhou 2019的更多相关文章
- 计蒜客 41391.query-二维偏序+树状数组(预处理出来满足情况的gcd) (The Preliminary Contest for ICPC Asia Xuzhou 2019 I.) 2019年徐州网络赛)
query Given a permutation pp of length nn, you are asked to answer mm queries, each query can be rep ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 E XKC's basketball team [单调栈上二分]
也许更好的阅读体验 \(\mathcal{Description}\) 给n个数,与一个数m,求\(a_i\)右边最后一个至少比\(a_i\)大\(m\)的数与这个数之间有多少个数 \(2\leq n ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 E. XKC's basketball team
题目链接:https://nanti.jisuanke.com/t/41387 思路:我们需要从后往前维护一个递增的序列. 因为:我们要的是wi + m <= wj,j要取最大,即离i最远的那个 ...
- 计蒜客 41387.XKC's basketball team-线段树(区间查找大于等于x的最靠右的位置) (The Preliminary Contest for ICPC Asia Xuzhou 2019 E.) 2019年徐州网络赛
XKC's basketball team XKC , the captain of the basketball team , is directing a train of nn team mem ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 【 题目:so easy】{并查集维护一个数的下一个没有被删掉的数} 补题ING
题意:给[1,n],n个数,有两种操作: 1 x,删去x2 x,查询还未被删去的数中大于等于x的最小的数是多少. input: output: 做法:按照并查集的方法压缩路径 代码: #include ...
- G.Colorful String(The Preliminary Contest for ICPC Asia Xuzhou 2019)
https://nanti.jisuanke.com/t/4 #include <bits/stdc++.h> using namespace std; ,; typedef unsign ...
- E.XKC's basketball team(The Preliminary Contest for ICPC Asia Xuzhou 2019)
https://nanti.jisuanke.com/t/41387 解: 离散化+线段树. #define IOS ios_base::sync_with_stdio(0); cin.tie(0); ...
- A.Who is better?(The Preliminary Contest for ICPC Asia Xuzhou 2019)
https://nanti.jisuanke.com/t/41383 解: 斐波那契博弈+中国剩余定理. #include <bits/stdc++.h> using namespace ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 E. XKC's basketball team (线段树)
题目链接:https://nanti.jisuanke.com/t/41387 题目大意:对于给定序列,求出对于每个位置求出比该数大于m的最靠右的位置. 思路:首先对序列进行离散化,然后对于每个数的下 ...
随机推荐
- jsp页面使用EL表达式 使用Jstl标签库中的标签,需要引入jstl.jar和standard.jar
spring boot 中使用jstl 首先在pom中加入 <dependency> <groupId>jstl</groupId> <artifactId& ...
- Java多线程——多线程方法详解
本系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线程的深入剖 ...
- head first 设计模式第一章笔记
设计模式是告诉我们如何组织类和对象以解决某种问题. 学习设计模式,也就是学习其他开发人员的经验与智慧,解决遇到的相同的问题. 使用模式的最好方式是:把模式装进脑子,然后在设计的时候,寻找何处可以使用它 ...
- 20191010-3 alpha week 1/2 Scrum立会报告+燃尽图 01
此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/8746 一.小组情况 组长:迟俊文 组员:宋晓丽 梁梦瑶 韩昊 刘信鹏 队名 ...
- day 37 CSS
参考博客:https://www.cnblogs.com/majj/p/9021419.html 1.CSS的三种链接样式: 行内链接(优先级最高) 内接样式 外接样式 <html lang=& ...
- 2019牛客暑期多校训练营(第二场)J.Subarray
题意:给你一个n 表示有n段连续的1序列 现在问你 在总长度为0~1e9-1的范围内有多少个大于0的子段 思路:假设我们统计了当前的前缀和 我们显然可以用树状数组维护一下前缀和 这样我们可以nlogn ...
- Erlang/Elixir精选-第1期
第1期(20191202) 文章 A short guide to the structure and internals of the Erlang distributed messaging fa ...
- Java 大黑话讲解设计模式 -- UML类图
目录 1.啥是UML类图? 2.UML类图有啥用? 3.正式理解UML类图 4.使用idea画第一个UML类图 5.类之间的关系图[必须牢记] 6.类之间的关系 6.1.依赖 6.2.泛化 6.3.实 ...
- 【数据结构】之栈(C语言描述)
栈(Stack)是编程中最常用的数据结构之一. 栈的特点是“后进先出”,就像堆积木一样,堆的时候要一块一块堆到最上面,拆的时候需要从最上面一块一块往下拆.栈的原理也一样,只不过它的操作不叫堆和拆,而是 ...
- python-模块,异常,环境管理器
模块 Module 什么是模块: 1.模块是一个包含有一系列数据,函数,类等组成的程序组 2.模块是一个文件,模块文件名通常以.py结尾 作用: 1.让一些相关数据,函数,类等有逻辑的组织在一起,使逻 ...