牛客小白月赛39 部分题解

比赛传送门:https://ac.nowcoder.com/acm/contest/11216

A题

给你一堆向量和一个目标向量,问你这一堆向量中的某两个的和能不能得到和目标向量平行的向量。
首先回顾一下向量的加法(x1 , y1) + (x2 , y2) == (x1 + x2 , y1 + y2)
由于数据量较小,所以可以将所有的向量归一化,相当于都平移到原点,从原点开始。然后分别计算两两向量之和,判断是否和目标向量平行即可,即判断yy * ob.x == xx * ob.y 能用乘法就别用除法,会有精度问题!!!
AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool cmp(int a , int b){
    return a > b;
}
struct node{
    int x;
    int y;
}a[1005];
int main() {
    int t = 0;
    int flag = 0;
    cin>>t;
    for(int i = 0 ; i  < t ;i ++){
        int x1 , y1 , x2 , y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        a[i].x = x1 - x2;
        a[i].y = y1 - y2;
    }
    int X1 , X2 , Y1 , Y2;
    scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
    node ob ;
    ob.x = X1 - X2;
    ob.y = Y1 - Y2;
    for(int i = 0 ; i < t ; i ++){
        for(int j = i + 1 ; j < t ; j ++){
            int xx = (a[i].x + a[j].x);
            int yy = (a[i].y + a[j].y);
            if(yy * ob.x == xx * ob.y)
            {
                flag = 1;
                break;
            }
        }
        if(flag == 1)
            break;
    }
    if(flag == 1)
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
    return 0;
}

B题

签到,没什么说的

#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool cmp(int a , int b){
    return a > b;
}
int main() {
    string s = "";
    cin>>s;
    int index = 0;
    for(int i = 0 ;  i < s.length() ;i ++){
        if(s[i] == 'Q' && s[i+1] == 'A' && s[i+2] == 'Q'){
            index = i;
            break;
        }
           
    }
    cout<<index + 1<<endl;
    return 0;
}

C题

可以看成一个爬格子的问题,两个人的起点都为0,问你两个人最多同样大的次数(这道题主要难度在于读题)。解法很简单,只需要比较一下上一次的最大值和这一次的最小值的关系,如果上一次的最大值比这一次的最小值要小(或者等于),那么加上这两个的差值 + 1即可,否则什么也不加,如果上次两个人相等的话还要减1,因为这个相等的算了两次。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main(){
    int n = 0;
    int ans = 0;
    cin >> n;
    static int a[3000005] = {0};
    static int b[3000005] = {0};
    for(int i = 1 ; i <= n ; i ++){
        scanf("%d%d",&a[i],&b[i]);
    }
    for(int i = 1 ; i <= n ; i++){
        ll x = max(a[i - 1] , b[i - 1]);//上一次最大的
        ll y = min(a[i] , b[i]);//这一次最小的
        if(x <= y)
            ans += (y - x + 1);
        if(a[i - 1] == b[i - 1])
            ans --;
    }
    cout << ans << endl;
    return 0;
}

E题

二进制计算问题,很简单,但是注意一下在计算的过程中使用long long,不然有可能爆整型

#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool cmp(int a , int b){
    return a > b;
}
int main() {
    int n = 0;
    cin>>n;
    ll ans = 0;
    while(n--){
        int a[100005] = {0};
        ll x = 0;
        scanf("%lld" , &x);
        int index = 0;
        while(x != 0){
            a[index] = x % 2;
            index ++;
            x /= 2;
        }
        int p = 0;
        for(int i = index - 1 ; i >= 0 ; i --){
            ans += (ll)(a[i] * (ll)pow(2 , p));//注意
            p ++;
        }
    }
    printf("%lld\n" ,ans);
    return 0;
}

H题

前缀和算一下打到这里需要多少次斩杀(不用魔法),后缀和算一下打到这里需要多少次斩杀(不用魔法)。然后计算一下对任意两个相邻的使用魔法,还需要多少次斩杀,即计算 l[i] + r[i + 3]) 的最小值。注意循环开始和结束的下标。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6 + 5;
int a[N];
int b[N];
ll l[N];
ll r[N];
int main(){
    int n = 0 ;
    cin >> n;
    for(int i = 1 ; i <= n ; i ++){
        scanf("%d",&a[i]);
        b[i] = a[i];
    }
    for(int i = 1 ; i <= n ; i ++){
        l[i] = a[i] + l[i - 1];
        a[i+1]=max(0,a[i+1]-a[i]);
        a[i+2]=max(0,a[i+2]-a[i]);
    }
    for(int i = n ; i >= 1 ; i--){
        r[i] = b[i] + r[i + 1];
        b[i-1]=max(0,b[i-1]-b[i]);
        b[i-2]=max(0,b[i-2]-b[i]);
    }
    ll ans = 2e18;
    for(int i = 0 ; i + 3 <= n + 2; i ++)
        ans = min(ans , l[i] + r[i + 3]);
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值