2020牛客多校第三场题解

A. Clam and Fish

签到。题意比较麻烦,注意桌子上只有饵料的时候也可以不拿,利用之前的饵料钓鱼

#include <bits/stdc++.h>
using namespace std;

int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n; scanf("%d",&n);
        string s; cin >> s;
        int ans = 0, er = 0;
        for(int i=0;i<n;i++) {
            if(s[i]=='0'&&er) ans++,er--;
            if(s[i]=='1') er++;
            if(s[i]=='2'|| s[i]=='3') ans++;
        }
        ans += er/2; //这一行是关键,把所有之前收饵料的环节的一半用来钓鱼,保证最大化
        printf("%d\n",ans);
    }
}

B. Classical String Problem

题意

两种操作,A x 代表输出字符串第x个字符,M x代表将字符串左移位/右移位x个位置。

解题

签到,本质是下标取模。注意由于字符串长度和询问组数比较多,所以变化量delta需要取模防止溢出。同时cin/cout可能超时。

#include <bits/stdc++.h>
using namespace std;

int main() {
//    freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false);
    string s; cin >> s;
    int len = s.length();
    int t; cin >> t;
    int d = 0;
    while(t--) {
        char a; cin >> a;
        int b; cin >> b;
        if(a=='A') cout<<s[(b-1+d)%len]<<endl;
        else d+=len+b;
        d = d%len+len;
    }
}

C. Operation Love

根据固定的几何图形判断左右手。比赛时由于精度过高一直WA。思路就是先判断好四个关键点,之后再根据左手和右手底边到下一条边叉积的正负不同来进行判断。注意,精度1e-4可以通过,但是更高的精度将无法通过。

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-4;
struct point {
    double x,y;
}data[25];

double dis(point aa, point bb) {
    return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));
}

double cross(point aa, point bb, point cc) {
    return (bb.x-aa.x)*(cc.y-aa.y)-(cc.x-bb.x)*(bb.y-aa.y);
}

int same(double a, double b) {
    if(fabs(a-b)<eps) return 1;
    return 0;
}

int main() {
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d", &t);
    while(t--) {
        for(int i=0;i<20;i++) {
            scanf("%lf%lf", &data[i].x, &data[i].y);
        }    
        int d1=0, d2=0, d3=0, flag=0;
        for(int i=0;i<20;i++) {
            d1=i,d2=(i+1)%20,d3=(i+2)%20;
            if(same(dis(data[d1],data[d2]), 9)) {
                if(cross(data[d1],data[d2],data[d3]) > 0 && same(dis(data[d2],data[d3]),6) ||
                   cross(data[d1],data[d2],data[d3]) < 0 && same(dis(data[d2],data[d3]),8))  {
                       puts("left"); flag=1; break;
                }
            }
        }
        if(!flag) puts("right");
    }
}

F. Fraction Construction Problem

题意

给定正整数
,满足

数据范围

解题

化简得
首先若ab不互质,则可以轻松构造出一组解d=b/gcd(a,b), f=1
ab互质,则将b分解为互质的两个数之积(不互质则ab不互质),之后根据exgcd求解方程,注意符号的正负,暴力卡过去。
要尽量把不必要的long long开成int防止超时

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

inline int gcd(int a, int b) {
    return b ? gcd(b, a%b) : a;
}

inline ll exgcd(ll a, ll b, ll &x, ll &y) {
    if(b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = exgcd(b, a%b, x, y);
    ll z = x;
    x = y;
    y = z - y * (a/b);
    return d;
}

int a, b, d, f;
ll c, e;

int main() {
//    freopen("in.txt", "r", stdin);
    int t;
    scanf("%d",&t);
    while(t--) {
        scanf("%lld%lld",&a,&b);
        int g = gcd(a,b);
        if(b == 1) printf("-1 -1 -1 -1\n");
        else if(g!=1) {
            printf("%d %d %d %d\n",(a+b)/g,b/g,1,1);
        } else {
            int flag = 0;
            for(int i=2; i*i<b; i++) {
                if(b%i==0 && gcd(i,b/i)==1) {
                    d = i;
                    f = b/i;
                    flag = 1;
                    break;
                }
            }
            if(!flag) printf("-1 -1 -1 -1\n");
            else {
                exgcd(f, d, c, e);
                c *= 1LL*a;
                e *= 1LL*a;
                if(c > 0 && e < 0)
                    printf("%lld %d %lld %d\n",c,d,-e,f);
                else 
                    printf("%lld %d %lld %d\n",e,f,-c,d);
            }
        }
    }
}

G. Operating on a Graph

题意

给一个 个点的 Graph,第 i 个点一刚开始是第 种颜色,接着有 k 次 操作,第 i 次操作有个参数 代表颜色 会侵略所有和自己相邻的颜色, 于是所有和 相邻的颜色全都变成 (若已没有颜色 已被侵略,则该次操作无效),求最终每个点的颜色。

解题

并查集

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6;
vector <int> a[maxn], temp;
int fa[maxn];
void init(int n) {
    for(int i = 0; i<=n; i++) fa[i]=i;
}
int find(int x) {
    return (fa[x] == x)?x:fa[x] = find(fa[x]);
}
int n,m,x,y,q,o,t;

int main() {
//    freopen("in.txt","r",stdin);
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&m);
        init(n);
        for(int i=0;i<=n;i++) a[i].clear();
        while(m--) {
            scanf("%d%d",&x,&y);
                a[x].push_back(y),
                a[y].push_back(x);
        }
        scanf("%d",&q);
        while(q--) {
            scanf("%d",&o);
            if(fa[o]!=o) continue; // 不存在这种颜色,直接取消操作
            temp = a[o];
            a[o].clear(); 
            for(int i=0;i<temp.size();i++) { // 遍历每个相邻的点
                int f = find(temp[i]);
                if(f != o) {
                    fa[f] = o;
                    // 本质上就是合并两个动态数组a[o]和a[f]
                    if(a[o].size()<a[f].size())
                        swap(a[o],a[f]);
                    for(int j=0; j<a[f].size(); j++)
                        a[o].push_back(a[f][j]);
                }
            }
        }
        for(int i=0;i<n;i++) {
            printf("%d ", find(i));
        }
        printf("\n");
    }
}

L. Problem L is the Only Lovely Problem

签到。判断字符串首是否有lovely,用了个新学的函数。

string :: find(string substring)
返回字符串在母串中的起始下标位置(下标记录),如果没有找到,那么会返回s.npos
全部评论

相关推荐

不愿透露姓名的神秘牛友
09-30 19:49
起名星人:蛮离谱的,直接要求转投销售
投递汇川技术等公司10个岗位
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务