牛客练习赛83 ABCE题

Posted CCSU_Cola

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客练习赛83 ABCE题相关的知识,希望对你有一定的参考价值。

A. 追求女神
题目链接
思路:因为人需要在固定的时间到达某个点,故当前位置到下一个位置最短所需时间加上当前时间若大于给出时间,则不可能达到目的,且因为人不可以站在原位置不动,如果给出时间大于最短所需时间,则人需要来回走动来消耗时间,每次走出当前点再回到当前的时间差一定为偶数,故若给定时间-当前时间得到的时间差的奇偶性和最短所需时间的奇偶性相同则可以达到目的,否则不能够达到。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		int x=0,y=0,a,b,k,e=0;
		int flag=1;
		for(int i=1;i<=n;i++){
			scanf("%d%d%d",&k,&a,&b);
			int w=abs(a-x)+abs(b-y);
            k=k-e;//得到时间差
			if(w>k){
				flag=0;
			}
            else if(w<k){
                int tt=k-w;
                if(tt%2)flag=0;
            }
            e=k+e;
            x=a,y=b;
		}
		if(flag)printf("Yes\\n");
		else printf("No\\n");
	}
}

B.计算几何
题目链接
思路:维护一个前缀和,即0到i区间中的二进制下 1 的个数有奇数个的总数,然后通过前缀R-前缀(L-1)即为答案,打表可知若i为奇数,则个数为 i / 2 + 1 i/2+1 i/2+1,若为偶数则判断自身是否为二进制下有奇数个1的数,若是则为它-1的奇数的总数+1个,不是则与它-1的奇数的总数相同。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll f(ll n){
    ll res=n>>1;
    if(n%2==1)return n/2+1;
    int cnt=0;
    while(n){
        if(n&1)cnt++;
        n/=2;
    }
    if(cnt%2)return res+1;
    return res;
}
int main(){
	ll n,m;
    int t;
    scanf("%d",&t);
    while(t--){
	scanf("%lld%lld",&n,&m);
	printf("%lld\\n",f(m)-f(n-1));
    }
    return 0;
}

C.集合操作
题目链接
思路:直接用大根堆模拟一下就可以通过,应该不是正解,可能是题目数据太水,在模拟的思路下我加了一点点的优化,就是每次取出大根堆的两个数,最大-第二大的差值/p+1即为最大的数需要减的次数,因为只有减去这么多次之后,他才会比第二大的数小。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
priority_queue<ll>q;
ll pp[1000100];
int main(){
     ll  n,k,p;
    scanf("%lld%lld%lld",&n,&k,&p);
    ll x;
    for(int i=1;i<=n;i++){
        scanf("%lld",&x);
        q.push(x);
    }
    if(n>1){
    while(k&&p!=0){
        ll f=q.top();
        q.pop();
        ll c=(f-q.top())/p+1;
        c=min(k,c);
        f=f-c*p;
        k=k-c;
        q.push(f);
    }
    }
    else{
        ll f=q.top();
        q.pop();
        f=f-k*p;
        q.push(f);
    }
    int idx=0;
    while(!q.empty()){
        pp[idx++]=q.top();
        q.pop();
    }
    for(int i=idx-1;i>=0;i--){
        printf("%lld ",pp[i]);
    }
    return 0;
}

E.小L的疑惑
思路:两个硬币分别叫做a,b。由两个硬币互素可知gcd(a,b)==1,由裴蜀定理可以知道,ax+by=c在不考虑x和y正负的情况下一定有解,但是题目条件很明显知道x和y不能为0,但当c>=ab的时候一定有解,因为当x=0,y=a或x=b,y=0的时候即为ab,大于它的时候也一定有解,因为aX1+bY1=1有解,且此解的x和y一定一正一负,若x为负,它一定会小于b,因为大于等于b的话,y=a,可以抵消掉a*b,没有实际意义,即a(x+X1)+b(y+Y1)=ab+1在(x+X1)和(y+Y1)为非负的前提下一定有解,所以ab+2,ab+3…都可以这样证明。于是我们只要考虑小于ab的部分即可,因为当c=ab的时候,x=0,y=a或x=b,y=0,且ax1+by1=-a-b的解为x=-1,y=-1,所以a(x1+x)+b(y1+y)=ab-a-b在(x1+x)和(y1+y)为非负的情况下一定无解,所以第一大,既然ab-a-b无解,那么在此前提下aX2+bY2=-a或aX2+bY2=-b与a(x1+x)+b(y1+y)=ab-a-b相加也是无解的。于是可以根据这个关系直接算出第k大不可得到的数。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[10000007];
int main(){
    ll a,b,k;
    int d1=1,d2=1;
    scanf("%lld%lld%lld",&a,&b,&k);
    dp[1]=a*b-a-b;
    for(int i=2;i<=k;++i){
        dp[i]=max(dp[d1]-a,dp[d2]-b);
        if(dp[i]==dp[d1]-a)d1++;
        if(dp[i]==dp[d2]-b)d2++;
    }
    printf("%lld\\n",dp[k]);
    return 0;
}

以上是关于牛客练习赛83 ABCE题的主要内容,如果未能解决你的问题,请参考以下文章

牛客练习赛83 E.牛客推荐系统开发之标签重复度

牛客练习赛83 C.集合操作(二分,单调性)

牛客练习——吐泡泡(简单的栈的运用题:别被多组输入恶心到了)

牛客练习赛D数学家的谜题线段树+bitset优化

转载:牛客练习赛17 c 规律题

牛客练习赛82总结+题解(只有A题Mocha 的字符串)