0
点赞
收藏
分享

微信扫一扫

牛客月月赛48

龙毓七七 2022-05-03 阅读 29
数据结构

小白月月赛48

写在前面:感觉实习之后好久好久没有更新blog了,昨天人生中第一次找女孩子搭讪要到了微信,到现在都感觉有点心跳过快(怂比本比了)。恭亲王府之行也因为一大早的突击核酸又搁置了,今天不想看论文趁闲打了场重现赛,除了手速不如以前了感觉一切还是在本科实验室时的情形,还是蛮开心的。

比赛网址

A. 孤独的数组
在这里插入图片描述
思路: Ai-1和Ai暴力求gcd即可,如存在gcd不为1,输出-1,否则输出0。

代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f, x) memset(f, x, sizeof(f))
using namespace std;
const int M = 1e4 + 50;
const int N = 1e5 + 50;
int n;

int gcd(int x, int y){
    return y == 0 ? x : gcd(y, x%y);
}

int main(){
    int cur, next;
    cin >> n;
    cin >> cur;
    int ans = 0;
    for(int i = 1; i < n; i++){
        cin >> next;
        if(gcd(cur, next) != 1){
            ans = -1;
        }
        cur = next;
    }
    printf("%d\n", ans);
    return 0;
}

B. 博弈大师

在这里插入图片描述
思路: 很容易想到,谁的技能卡多,谁就能赢(如果最终处于必输态,只要用技能卡转换操作者,将输态转移给对方即可,对方使用技能卡转移状态时,我方也可使用技能卡抵消),当两方技能卡数量相同时,相当于谁都没有卡,看常规轮流操作操作的输赢即可,这个操作轮数可以用二分求解。

代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f, x) memset(f, x, sizeof(f))
using namespace std;
const int M = 1e4 + 50;
const int N = 1e5 + 50;

ll BiSearch(ll x){
    ll L = 0, R = 1e9;
    ll mid;
    while(L <= R){
        mid = (L+R)>>1;
        ll tmp = (mid+1)*mid/2;
        if(tmp == x) return mid+1;
        if(tmp > x)
            R = mid-1;
        else
            L = mid+1;
    }
    return L;
}

int main(){
    int t;
    cin >> t;
    while(t--){
        ll n, a, b;
        cin >> n >> a >> b;
        if(a > b) cout << "niuniu\n";
        if(a < b) cout << "niumei\n";
        if(a == b){
            ll res = BiSearch(n);
            if(res&1) cout << "niuniu\n";
            else cout << "niumei\n";
        }
    }
    return 0;
}

C. 可疑的区间
在这里插入图片描述
思路: 先考虑求有趣值,就是求我们设定的长度为len的区间和这n个有趣区间中有交集的个数。很典型的线段树或者树状数组,这里直接求是否有交集情况比较复杂,可以考虑容斥:n - 没有交集的区间数。没有交集的区间有两种情况:

  1. 有趣区间的右端点在设定区间的左端点左侧
  2. 有趣区间的左端点在设定区间的右端点右侧

我们只需要分别维护有趣区间左右端点的树状数组即可,同理求权重也只需要维护两个树状数组即可。一共4个树状数组,时间复杂度nlogn。

代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f, x) memset(f, x, sizeof(f))
using namespace std;
const int M = 1e7 + 50;
const int N = 1e7 + 50;
int m, n;
ll Lsum[N], Rsum[N];
int Lcnt[N], Rcnt[N];

void init(){
    mem(Lsum, 0);
    mem(Rsum, 0);
    mem(Lcnt, 0);
    mem(Rcnt, 0);
}

int lowbit(int x){
    return x&-x;
}

void update_Lsum(int x, int w){
    while(x < N){
        Lsum[x] += w;
        x += lowbit(x);
    }
}
void update_Rsum(int x, int w){
    while(x < N){
        Rsum[x] += w;
        x += lowbit(x);
    }
}

void update_Lcnt(int x){
    while(x < N){
        Lcnt[x] += 1;
        x += lowbit(x);
    }
}

void update_Rcnt(int x){
    while(x < N){
        Rcnt[x] += 1;
        x += lowbit(x);
    }
}

ll get_Lsum(int x){
    ll res = 0;
    while(x > 0){
        res += Lsum[x];
        x -= lowbit(x);
    }
    return res;
}

ll get_Rsum(int x){
    ll res = 0;
    while(x > 0){
        res += Rsum[x];
        x -= lowbit(x);
    }
    return res;
}

int get_Lcnt(int x){
    int res = 0;
    while(x > 0){
        res += Lcnt[x];
        x -= lowbit(x);
    }
    return res;
}

int get_Rcnt(int x){
    int res = 0;
    while(x > 0){
        res += Rcnt[x];
        x -= lowbit(x);
    }
    return res;
}

int get_interest(int L, int R){
    return get_Lcnt(R)-get_Rcnt(L);
}

ll get_weight(int L, int R){
    return get_Lsum(R)-get_Rsum(L);
}

int main(){
    cin >> n >> m;
    init();
    int x, y;
    int p_min = 5e6 + 50, p_max = 1;
    for(int i = 1; i <= n; i++){
        cin >> x >> y;
        update_Lsum(x, i);
        update_Rsum(y, i);
        update_Lcnt(x);
        update_Rcnt(y);
        p_min = min(min(p_min, x), y);
        p_max = max(max(p_max, x), y);
    }
    int ans = 0;
    int max_interest = 0;
    ll max_w = 0;
    for(int i = max(1, p_min-m+1); i <= p_max; i++){
        int L = i, R = i+m-1;
        int interest = get_interest(L-1, R);
        if(max_interest < interest){
            max_interest = interest;
            max_w = get_weight(L-1, R);
            ans = 1;
        }
        else if(max_interest == interest){
            ll weight = get_weight(L-1, R);
            if(max_w < weight){
                max_w = weight;
                ans = 1;
            }
            else if(max_w == weight){
                ans++;
            }
        }
    }
    cout << ans << "\n";
    return 0;
}

D. 交替加乘
在这里插入图片描述
思路: 很容易想的贪心,排序后前半部分用做加法,后半部分用作乘法。考虑加法内部顺序,先加大的能乘更多次,肯定会比较大;考虑乘法内部顺序,后乘大的,后面大的乘的做了更多的加法,基数更大,肯定结果也会更大。

代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f, x) memset(f, x, sizeof(f))
using namespace std;
const int M = 1e5 + 50;
const int N = 1e5 + 50;
const int MOD = 1e9 + 7;
int m, n;
int a[N];
int main(){
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
        scanf("%d", a+i);
    sort(a, a+n);
    a[n] = 1;
    int mid = n/2;
    ll res = a[mid];
    for(int i = mid-1, j = mid+1; i >= 0; i--, j++){
        res = res+a[i];
        res = (res*a[j])%MOD;
    }
    printf("%lld\n", res);
    return 0;
}

E. 或与异或
在这里插入图片描述
思路: 没啥好讲的,倒水问题dfs或者bfs搜索的裸题。
代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f, x) memset(f, x, sizeof(f))
using namespace std;
const int M = 1e5 + 50;
const int N = 1e5 + 50;
const int MOD = 1e9 + 7;
ll a, b, target;
bool ans = 0;
map<pair<ll, ll>, bool> mp;
void dfs(ll x, ll y){
    if(x == target || y == target){
        ans = 1;
        return;
    }
    if(!ans){
        if(!mp.count({x|y, y}) && !mp.count({y, x|y})){
            mp[{x|y, y}] = mp[{y, x|y}] = 1;
            dfs(x|y, y);
        }
        if(!mp.count({x, x|y}) && !mp.count({x|y, x})){
            mp[{x, x|y}] = mp[{x|y, x}] = 1;
            dfs(x, x|y);
        }
        if(!mp.count({x&y, y}) && !mp.count({y, x&y})){
            mp[{x&y, y}] = mp[{y, x&y}] = 1;
            dfs(x&y, y);
        }
        if(!mp.count({x, x&y}) && !mp.count({x&y, x})){
            mp[{x, x&y}] = mp[{x&y, x}] = 1;
            dfs(x, x&y);
        }
        if(!mp.count({x^y, y}) && !mp.count({y, x^y})){
            mp[{x^y, y}] = mp[{y, x^y}] = 1;
            dfs(x^y, y);
        }
        if(!mp.count({x, x^y}) && !mp.count({x^y, x})){
            mp[{x, x^y}] = mp[{x^y, x}] = 1;
            dfs(x, x^y);
        }
    }
}

int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        mp.clear();
        scanf("%lld %lld %lld", &a, &b, &target);
        mp[{a, b}] = mp[{b, a}] = 1;
        ans = 0;
        dfs(a, b);
        if(ans)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

F. 孤独的树
在这里插入图片描述
思路: 简单的树形dp,从叶子节点往根节点搜,统计gcd的质因子个数。
代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f, x) memset(f, x, sizeof(f))
using namespace std;
const int M = 1e3 + 50;
const int N = 1e5 + 50;
const int MOD = 1e9 + 7;
int n;
int val[N];
int head[N], cnt;
bool vis[M];
int su[M], ct;
ll ans = 0;

struct edge{
    int to;
    int next;
    edge():to(0), next(0){}
    edge(int tt, int nn):to(tt), next(nn){}
}e[2*N];

void init(){
    for(int i = 0; i <= n; i++)
        val[i] = head[i] = 0;
    cnt = ct = 0;
    mem(vis, 1);
    vis[0] = vis[1] = 0;
    for(int i = 2; i < M; i++){
        if(vis[i]){
            su[ct++] = i;
            for(int j = i*i; j < M; j += i)
                vis[j] = 0;
        }
    }
    ans = 0;
}

int gcd(int x, int y){
    return y == 0 ? x : gcd(y, x%y);
}

void add(int x, int y){
    e[++cnt] = edge(y, head[x]);
    head[x] = cnt;
}

int get_op_num(int x){
    int res = 0;
    int up = sqrt(x);
    for(int i = 0; su[i] <= up; i++){
        while(x%su[i] == 0){
            x /= su[i];
            res++;
        }
    }
    if(x > 1) res++;
    return res;
}

void dfs(int x, int pre){
    for(int i = head[x]; i; i = e[i].next){
        int to = e[i].to;
        if(to == pre) continue;
        dfs(to, x);
        int tmp = gcd(val[x], val[to]);
        val[x] /= tmp;
        ans += get_op_num(tmp);
    }
}

int main(){
    scanf("%d", &n);
    init();
    for(int i = 1; i <= n; i++)
        scanf("%d", val+i);
    int x, y;
    for(int i = 1; i < n; i++){
        scanf("%d %d", &x, &y);
        add(x, y);
        add(y, x);
    }
    dfs(1, 0);
    printf("%lld\n", ans);
    return 0;
}

举报

相关推荐

0 条评论