牛客练习赛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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值