2021牛客小白月赛39
2021牛客小白月赛39(A+B+C+E+G+H)
- A.憧憬
- B.欢欣
- C.奋发
- D.绝望
- E.迷惘
- F.孤独
- G.冷静
- H.终别
A.憧憬
题目链接:https://ac.nowcoder.com/acm/contest/11216/A
题目描述:
给定n个向量的起点和终点x1,y1,x2,y2,再给出一个目标向量,求能否由n个向量中的两个相加构造出一个与目标向量平行的向量(注意,平行包括方向相同或相反)
保证x1!=x2,y1!=y2,保证两个向量相加不为零向量。
输入描述:
第一行给定一个整数n
接下来n行每行四个整数x1,y1,x2,y2,表示第i个向量的起点和终点
最后一行给出四个整数x1,y1,x2,y2,表示目标向量的起点和终点
1<=n<=1000,1<=x1,y1,x2,y2<=10000
输出描述:
若可以,输出“YES”
否则输出“NO”(均不含引号)
示例1
输入
5
1 2 4 8
2 4 5 10
1 2 2 4
3 5 4 6
6 10 7 11
1 1 4 7
输出
YES
说明
1号向量与3号向量相加
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
struct node{int x,y;
}a[N];
int main()
{int n;scanf("%d",&n);for(int i=1;i<=n;i++){int x1,y1,x2,y2;cin>>x1>>y1>>x2>>y2;a[i].x=x2-x1;a[i].y=y2-y1;}int x1,y1,x2,y2,x3,y3;cin>>x1>>y1>>x2>>y2;x3=x2-x1,y3=y2-y1;int m1=__gcd(x3,y3);x3/=m1;y3/=m1;int flag=0;for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){int x0=a[i].x+a[j].x;int y0=a[i].y+a[j].y;int m0=__gcd(x0,y0);x0=x0/m0;y0=y0/m0;if(x0==x3&&y0==y3){cout<<"YES";return 0;}}}cout<<"NO";return 0;
}
签到题之一,高中数学向量知识。。。求出两个向量a,b(用终点向量减起点向量),c=a+b求出和向量,假如c(x,y),目标向量为(x1,y1),那么直接判断x乘y1是否等于y乘x1即可,如果是就为"YES",否则就为"NO".我做的时候想的稍微复杂点,用了最大公约数,其实大可不必,直接这样判断更简单。
B.欢欣
题目链接:https://ac.nowcoder.com/acm/contest/11216/B
题目描述:
兴趣使然,他加入了Oier的行列,很快,他就学会了发QAQ……
小P非常喜欢发QAQ,但是他经常不慎打错,请你帮帮他在他的话里找到第一个正确的QAQ吧!
给定一个字符串,输出第一个QAQ的位置(保证有解)
输入描述:
一行一个字符串
3<=len<=10^6,len表示字符串长度
输出描述:
输出一个数,表示第一个QAQ中第一个Q的位置
示例1
输入
qAQaqQAqQAQ
输出
9
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
string s;
int main()
{cin>>s;int len=s.length();int flag=0,pos;for(int i=0;i<len;i++){if(s[i]=='Q'&&s[i+1]=='A'&&s[i+2]=='Q'){cout<<i+1;return 0;} }return 0;
}
最简单的签到题,直接判断即可,这里就不多说了。
C.奋发
题目链接:https://ac.nowcoder.com/acm/contest/11216/C
code:
#include<bits/stdc++.h>
using namespace std;
const int N=3e6+10;
long long ans=0;
int a[N],b[N];
int main()
{int n;cin>>n;for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);for(int i=1;i<=n;i++){int l=min(a[i],b[i]);int r=max(a[i-1],b[i-1]);if(l>=r){ans+=l-r;if(a[i-1]!=b[i-1]) ans++;}}printf("%lld",ans);return 0;
}
这道题我理解错意思了…呜呜呜~看完题解才知道这道题原来不是那么难。这题是严重被榜带歪的题。。。比赛时只有34人写出来:)。我当时也被吓到了,再加上理解错题意,就寄了。按照题意,a,b两个序列为递增序列,所以直接暴力模拟即可。
D.绝望
题目链接:https://ac.nowcoder.com/acm/contest/11216/D
明天更。。。
E.迷惘
题目链接:https://ac.nowcoder.com/acm/contest/11216/E
code:
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
vector<int> a;
long long ans=0;
void init(int n)
{while(n){if(n&1) a.pb(1);else a.pb(0);n=n/2;}}
int ksm(int x,int y)
{int res=1;while(y){if(y&1) res=res*x;x=x*x;y/=2;}return res;
}
int main()
{int n;cin>>n;while(n--){int num;cin>>num;if(num==0){continue;}a.clear();init(num);reverse(a.begin(),a.end());for(int i=a.size()-1;i>=0;i--){if(a[i]==0)a.pop_back();else{break;}}reverse(a.begin(),a.end());int len1=a.size()-1;for(int i=0;i<a.size();i++){ans+=a[i]*ksm(2,len1);len1--; } }cout<<ans<<"\n";return 0;
}
签到题之一,但这道题我又理解错意思了,wa了三发,啊啊啊啊,好烦!我之前的理解是分别求出来,正确的理解是分别求出来的数的和。。。而中间又因为一些细节上没做处理,所以wa了三发。这道题不是太难,我用了vector,但可以不用的,做法很多,不过我想锻炼自己用数据结构的能力,所以用了数据结构的知识。
F.孤独
题目链接:https://ac.nowcoder.com/acm/contest/11216/F
以后更。。。
G.冷静
题目链接:https://ac.nowcoder.com/acm/contest/11216/G
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+5;
int vis[N],p[N],f[N],ans[N],c[N];
struct Query{int n,k,id;
}query[N];
void init()
{ int tot=0;memset(vis,0,sizeof(vis));memset(p,0,sizeof(p));vis[0]=vis[1]=1;for(int i=2;i<=N;i++){if(vis[i]==0){p[tot++]=i;f[i]=i;}for(int i1=0;i1<tot&&N>=p[i1]*i;i1++){vis[i*p[i1]]=1;f[i*p[i1]]=p[i1];if(i%p[i1]==0) break;}}}
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
bool compare1(Query x,Query y)
{return x.n<y.n;
}
void ins(int x) {for(;x<=10000000;x+=x&-x) ++c[x];}
int ask(int x) {int r=0;for(;x;x-=x&-x) r+=c[x];return r;}
int main()
{init();int q;q=read();for(int i=1;i<=q;i++){query[i].n=read();query[i].k=read();query[i].id=i;}sort(query+1,query+1+q,compare1);for(int i=1,j=1;i<=q;i++){ while(j<query[i].n) ins(f[++j]);ans[query[i].id]=query[i].n-1-ask(query[i].k-1);}for(int i=1;i<=q;i++)cout<<ans[i]<<"\n";return 0;
}
这道题用了欧拉筛,离线查询和树状数组,也可以不用树状数组,可以用线段树,平衡树,但不管是哪个树我都不会。。。我好弱呜呜呜。看了题解和大佬的视频的讲解勉强弄懂了,写出了AC代码来。就是树状数组那里为什么要那样写我没搞明白,但我理解它那样做的用途,这就很尴尬了。
题目的意思是要让你求1~n中有多少个数可以由不小于k的质数的乘积来表示,注意质数可以为1个,也可以为多个。我们的做法是:用欧拉筛算出i的最小质因子f[i],然后用struct 结构体将q次查询的n,k,i储存起来,i为查询顺序数。然后根据n的大小来用sort排序,排序是从小到大。然后遍历,算出当前n的答案,并将答案储存在ans数组里,之后离线查询答案即可。在算当前n的答案时就用了树状数组来求。
1.欧拉筛筛出i的最小质因子:
void init()
{ int tot=0;memset(vis,0,sizeof(vis));memset(p,0,sizeof(p));vis[0]=vis[1]=1;for(int i=2;i<=N;i++){if(vis[i]==0){p[tot++]=i;f[i]=i;}for(int i1=0;i1<tot&&N>=p[i1]*i;i1++){vis[i*p[i1]]=1;f[i*p[i1]]=p[i1];if(i%p[i1]==0) break;}}}
有一点要注意的是,f[i]是会更新的!比如在欧拉筛中i=4时,算出的f[4✖3]=3,也就是f[12]=3,显然是错的,但不要因为这个就否定上述这个做法,因为f[6✖2]=2!而且这个是一定会更新到正确答案的。
2.存储n,k,i,并sort排序:
struct Query{int n,k,id;
}query[N];
bool compare1(Query x,Query y)
{return x.n<y.n;
}
for(int i=1;i<=q;i++){query[i].n=read();query[i].k=read();query[i].id=i;}sort(query+1,query+1+q,compare1);
3.遍历算出当前n的答案:
void ins(int x) {for(;x<=10000000;x+=x&-x) ++c[x];}
int ask(int x) {int r=0;for(;x;x-=x&-x) r+=c[x];return r;}
for(int i=1,j=1;i<=q;i++){ while(j<query[i].n) ins(f[++j]);ans[query[i].id]=query[i].n-1-ask(query[i].k-1);}
这里着重说下怎么求这个答案。先举个例子,假设当前n=5,k=3,2,3,4,5分别对应的最小质因子为2,3,2,5,那么:
也就是说最小质因子为2的数有两个,3的有一个,5的有一个,因为k=3,答案就从3和5里选,将这两个的总数相加即可,也就是1+1=2,答案就是2.如果之后的n为7,k为2,那么:
也就是2+1+1+1=5.以此类推就可求出答案。而就是这时候用树状数组来维护。
ins和ask函数就是树状数组的精髓部分了,ins函数是求出上面图片最小质因子对应有几个数,而ask函数则是将ins函数传进去的最小质因子对应的个数相加到ask的参数对应的最小质因子的个数为止,比如n为7,k为4的话,ask传进去3,ask函数的返回值就为2+1=3,答案就是n-1-3=3。
等明天弄懂了树状数组就解释这个做法的原理。
——————————————————————
懂了,树状数组的核心在于lowbit函数,也就是类似x&-x,返回值是二进制表示中最右的1,比如,10010,返回的二进制数就是10,对应的十进制数为2,在更新函数ins中我们就一直用lowbit函数来更新:
void ins(int x) {for(;x<=10000000;x+=x&-x) ++c[x];}
最大不超过数组的最大长度,从题目中我们就可得知应不超过3e6,适当大点也没关系。为什么要更新到数组最大长度呢?我觉得是为了以后的查询,在查询中会一直减lowbit函数,减到不能减为止,加起来的数就是我们要查询的值了,而如果在ins函数中不更新到最大长度,是得不了正确答案的。具体可见下图:
这两张图来自:https://blog.csdn.net/bestsort/article/details/80796531
大家可以参考上面的博客来学习树状数组。
第一张为十进制版本,第二张为二进制版本。绿色的为更新过程,黑色的为查询过程,所以这就很直观的能看出为什么要一直更新直到更新到数组最大长度了还有他的更新和查询的原理了。
H.终别
题目链接:https://ac.nowcoder.com/acm/contest/11216/H
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
#define ll long long
ll a[N],b[N],pre[N],last[N];
int main()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];b[i]=a[i];} for(int i=1;i<=n;i++){int d=max(0ll,b[i]);b[i]-=d,b[i+1]-=d,b[i+2]-=d;pre[i]=pre[i-1]+d;}for(int i=1;i<=n;i++)b[i]=a[i];for(int i=n;i>=2;i--){int d=max(0ll,b[i]);b[i]-=d,b[i-1]-=d,b[i-2]-=d;last[i]=last[i+1]+d;}if(n<=2){cout<<0;return 0;}ll ans=1e18;for(int i=1;i<=n;i++){ans=min(ans,pre[i-1]+last[i+2]);}cout<<ans;return 0;
}
这道题比较难,我们可以先假设没用魔法,那么就用贪心的策略,每次斩三只,这就能使斩击次数最少,用for循环遍历,每次都要砍到当前十七兽血量为0,如果当前的血量为负数或0就不用砍了,这样就是O(n)的复杂度,加上魔法的话,最简单的想法就是枚举用魔法的位置,每次枚举时都用上述的方法来砍,那么n*O(n)也就是O(n^2)的复杂度了。由于常数过大,n最大可为10的6次方,所以这样做必然超时。于是我们要想方法减小时间复杂度。
图片里的i和i+1代表的是魔法使用的位置,所以我们要求的就是前i-1位置总共的斩击次数加上i+2~n位置斩击次数。所以我们就会想到用前缀和数组pre,和后缀和数组last,分别储存斩击次数,那么当前的斩击次数就位pre[i-1]+last[i+2],算的时候是要选这些当中的最小值,故用上述图片里的式子,ans要设置为1e18,以防这两个数组相加大于一开始的ans,就是要保证一开始ans等于这两个数组相加。
2021牛客小白月赛39相关推荐
- F.孤独(牛客小白月赛39)
F.孤独(牛客小白月赛39) 题意: 给定一棵树,寻找一个路径,将断掉所有与这个路径上的点相连的边,使得剩下的最大连通块的大小最小 题解: 这题有点印象,感觉做过,至少这个方法肯定遇到过 设dp[u] ...
- F-选座椅_牛客小白月赛61 (nowcoder.com) 双指针,差分,2021济南ICPC- K Search For Mafuyu (pintia.cn) dfs
F-选座椅_牛客小白月赛61 (nowcoder.com) 双指针,差分 如果区间[l,r]满足所有条件,那么包含[l,r]的区间也一定是满足条件的,那就考虑双指针遍历每一个区间,如果当前区间满足条件 ...
- 牛客小白月赛16 小石的签到题(博弈)
牛客小白月赛16 小石的签到题 链接:https://ac.nowcoder.com/acm/contest/949/A来源:牛客网 题目描述 输入描述: 共一行,输入一个数 nnn . 输出描述: ...
- 牛客小白月赛58 B(暴力)C(思维)D(dp滚动数组优化)
牛客小白月赛58 感觉没什么意思,这场月赛出题人有点问题. B 题意:给定一定的数据填充顺序和每一个填充层的名称,只有填充满了上一层才可以填充下一层. 但是每一层又属于某一个大层,一个大层中包含了若干 ...
- 牛客小白月赛65个人题解A-E
1. 牛客小白月赛65 A. 牛牛去购物 题意:给定n元,购买价格为a元的篮球和价格为b的篮球,数量不定,要使得花掉的钱最多,也就是剩余的钱数最少,求这个值 (1 <= n, a, b < ...
- 牛客小白月赛24 J.建设道路
牛客小白月赛24 J.建设道路 题目链接 题目描述 牛牛国有 nnn 个城市,编号为 1-n,第 iii 个城市有一个价值 aia_iai ,牛国的国王牛阔落特别喜欢在牛牛国旅游,并且他不想每次旅游 ...
- 牛客小白月赛4 D.郊区春游
牛客小白月赛4 D.郊区春游 题目链接 题目描述 今天春天铁子的班上组织了一场春游,在铁子的城市里有 nnn 个郊区和 mmm 条无向道路,第 iii 条道路连接郊区 AiA_iAi 和 BiB_i ...
- 牛客小白月赛25 C.白魔法师
牛客小白月赛25 C.白魔法师 题目链接 题目描述 你是一个白魔法师. 现在你拿到了一棵树,树上有 个点,每个点被染成了黑色或白色. 你可以释放一次魔法,将某个点染成白色.(该点不一定是黑色点,也可以 ...
- 牛客小白月赛60(A~C)题解
原题地址:牛客小白月赛60_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ 题目A:小竹与妈妈 题意:输出(x-b)/a即可,没什么好说 代码: #include< ...
最新文章
- 简洁版本 STP/RSTP/MSTP的区别以及各自的特点
- Hypercolumns笔记
- MOSS publishing功能:创建页面到子文件夹
- java批处理 异常处理_Java批处理教程
- WampServer的配置
- 开课吧学python靠谱吗-学设计?学Python?看看我的人生是如何开挂!!!
- C语言实现加密解密功能 附带详细注释源码
- 几个常见的 Socket 连接错误及原因
- opencv使用trackbar调控美颜程度
- 【android】uiselectoer 自动化测试
- 移动办公——千脑云电脑 在线存储,中国人的在线办公室
- YUV的原始数据文件转rgb使用cv2显示
- 爬虫,爬取句子迷《龙族》
- UKEY通信CCID
- Maven Assembly插件介绍
- 2022年HELIUM3将引领链游开启gaming2.0时代
- 梯度下降法计算二次函数极值、拟合一次曲线、拟合二次曲线
- 小武学fpgastep3
- Nao机器人运行B-human代码之开始篇 1
- 如何查看 Mac ssh key
热门文章
- 283.软件体系结构描述
- OCZ REVODRIVE3 used in CentOS 5.x x64 on DELL R610 Server's PCI-E x4
- Spring实战(第4版)第2章 装配Bean
- Redis安装配置 -- 来自网络
- jsp21124公交卡充值管理系统的设计与实现mysql
- 回顾各种编码的创新和异同-MEPG2, MPEG4, H.264/AVC以及H.265/HEVC比较(转)
- 动态代理和静态代理各自的特点
- centos下修改hostname,ip,netmask,gateway,dns
- vue中用openlayers实现移动点动画
- 渗透学习日记day17