Codeforces Round #748 (Div. 3) A~E

本文介绍了三个C++实现的算法,分别涉及数组的最值问题、数字字符串处理和最大公约数计算。对于D1和D2问题,提出了将寻找模数转化为求最大公约数和枚举差值因子的方法。E问题中,通过拓扑排序解决节点深度限制问题。这些算法展示了在处理数组和数学问题时的有效策略。
摘要由CSDN通过智能技术生成

前言

其中A~C比较简单,就只放代码了;

D1,D2,E会有个人理解

F和G待补

A

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

int a[10];
void solve(){
    for(int i=1;i<=3;++i) cin >> a[i];
    int mx = 0;
    for(int i=1;i<=3;++i){
        mx = max(mx,a[i]);
    }
    int cnt = 0;
    for(int i=1;i<=3;++i){
        if(a[i] == mx) ++cnt;
    }
    if(cnt == 3){
        for(int i=1;i<=3;++i) cout << a[0]+1 << ' ';
        cout << '\n';
        return;
    }
    if(cnt == 2){
        for(int i=1;i<=3;++i){
            cout << mx - a[i] + 1 << ' ';
        }
        cout << '\n';
        return;
    }
    for(int i=1;i<=3;++i){
        if(a[i] == mx) cout << 0 << ' ';
        else cout << mx - a[i] + 1 << ' ';
    }
            cout << '\n';
}

int main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--) solve();
    return 0;
}

B

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 1e2 + 10;

char str[N];

void solve(){
    cin >> (str+1);
    int ans = 1e9;
    int n = strlen(str+1);
    for(int i=1;i<n;++i){
        for(int j=i+1;j<=n;++j){
            int now = (str[i]-'0')*10 + (str[j]-'0');
            if(now % 25 == 0){
                ans = min(ans,n-2-(i-1));
            }
        }
    }
    cout << ans << '\n';
}

int main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--) solve();
    return 0;
}

C

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 4e5 + 10;

int a[N],n,k;

void solve(){
    cin >> n >> k;
    for(int i=1;i<=k;++i){
        cin >> a[i];
    }
    sort(a+1,a+1+k);
    int ans = 0,cat = 0;
    for(int i=k;i>=1;--i){
        if(cat >= a[i]) break;
        ++ans;
        cat += n-a[i];
    }
    cout << ans << '\n';
}

int main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--) solve();
    return 0;
}

D1

因为我们最终要使得所有的数相等,那么我们可以转化一下思路;

我们可以认为,所有的数模某个数,它们都是同余的

那么我们的任务就变成了求最大的模数是多少;

我们假设模数为 k k k,那么我们让数组中的数两两做差;

这样得到的差值必然是 k k k倍数(我们就是要减去余数);

比如 x = a k + r , y = c k + r , x − y = ( a − c ) k x=ak+r,y=ck+r,x-y=(a-c)k x=ak+r,y=ck+r,xy=(ac)k;


假设这些差值为 d 1 , d 2 , . . . , d y d_1,d_2,...,d_y d1,d2,...,dy

那么答案必然是 g c d ( d 1 , d 2 , . . . , d y ) gcd(d_1,d_2,...,d_y) gcd(d1,d2,...,dy)

也就是说我们想让倍数尽可能小,而模数尽可能大,那么直接用gcd即可;

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 1e2 + 10;

int a[N];

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

void solve(){
    int n;
    cin >> n;
    for(int i=1;i<=n;++i) cin >> a[i];
    bool flag = 1;
    for(int i=2;i<=n;++i){
        if(a[1] != a[i]) {
            flag = 0;
            break;
        }
    }
    if(flag){
        cout << -1 << '\n';
        return;
    }
    vector<int> ve;
    for(int i=1;i<n;++i){
        for(int j=i+1;j<=n;++j){
            int dif = a[j] - a[i];
            dif = dif>=0?dif:-dif;
            if(dif != 0) ve.push_back(dif);
        }
    }
    int ans = ve[0];
    for(int i=1;i<ve.size();++i) ans = gcd(ans,ve[i]);
    cout << ans << '\n';
}

int main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--)
        solve();
    return 0;
}

D2

和上题一个思路,我们想使得一半的数模 k k k同余;

假设差值为 d 1 , d 2 , . . . , d y d_1,d_2,...,d_y d1,d2,...,dy

我们知道每个差值一定是某个数的倍数,而这个数就是模数;

我们想使得这个模数尽可能大,那么只需要枚举差值的因子并取max即可;

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <ctime>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 1e2 + 10;

int a[N],n,ans;
map<int,int> mp;

void ck(int x){
    mp.clear();
    for(int i=1,r;i<=n;++i){
        r = ((a[i]%x)+x)%x;
        if(++mp[r] >= n/2){
            ans = max(ans,x);
            break;
        }
    }
}
void solve(){
    mp.clear();
    cin >> n;
    for(int i=1;i<=n;++i){
        cin >> a[i];
        ++mp[a[i]];
    }
    for(auto x : mp){
        if(x.second >= n/2){
            cout << -1 << '\n';
            return;
        }
    }
    vector<int> ve;
    for(int i=1;i<n;++i){
        for(int j=i+1;j<=n;++j){
            int dif = a[j] - a[i];
            dif = dif>=0?dif:-dif;
            if(dif != 0){
                ve.push_back(dif);
            }
        }
    }
    mp.clear();
    ans = 1;
    for(auto x : ve){
        //最大的可能的贡献是x
        //如果x都小于ans,说明它的因子都没用
        if(x <= ans) continue;
        for(int p=1;p*p<=x;++p){
            if(x % p == 0){
                // x/p >= p,前者都没用,那后面必然不可能有用的
                if(x/p<=ans) break;
                ck(x/p);
                ck(p);
            }
        }
    }
    cout << ans << '\n';
}

int main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--)
        solve();
    return 0;
}

E

我们只需要拓扑排序一下,记录dep即可;

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <vector>

using namespace std;

typedef long long ll;

const int N = 4e5 + 10;

int in[N],n,k,dep[N];

vector<int> G[N];

vector<int> sorted;

void solve(){
    cin >> n >> k;
    sorted.clear();
    for(int i=1;i<=n;++i){
        in[i] = dep[i] = 0;
        G[i].clear();
    }
    for(int i=1,u,v;i<=n-1;++i){
        cin >> u >> v;
        ++in[u],++in[v];
        G[u].push_back(v);
        G[v].push_back(u);
    }
    queue<int> q;
    for(int i=1;i<=n;++i){
        if(in[i]==1){
            q.push(i);
            dep[i] = 1;
        }
    }
    while(!q.empty()){
        int u = q.front();
        sorted.push_back(u);
        q.pop();
        for(auto v : G[u]){
            --in[v];
            if(in[v]==1){
                q.push(v);
                dep[v] = dep[u] + 1;
            }
        }
    }
    int ans = 0;
    for(auto x : sorted){
        if(dep[x] > k) ++ans;
    }
    cout << ans << '\n';
}

int main(){
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--)
        solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值