Codeforces Round #629 (Div. 3)解题报告

题目链接

A.Divisibility Problem

题意
a b a 1 a b 给定a和b,每次a可以加1,问加多少的时候a能整除b aba1ab
题解
( a <mtext>   </mtext> <mtext>   </mtext> a % b ) 直接(a~-~a\%b)就可以了,特判一下原本就能取余的情况 (a  a%b)

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        int a,b;
        cin>>a>>b;
        if(a%b){
            cout<<b-(a%b)<<endl;
        }
        else cout<<0<<endl;
    }
    return 0;
}


B. K-th Beautiful String

题意
n 2 a 2 b 一个字符串包含n-2个a和2个b n2a2b
k 现在需要该字符串的第k字典序 k
题解
b 可以先确定第一个b的位置 b
b n i 如果第一个b在n-i的位置,第二个在最后 bni
i ( i + 1 ) / 2 那么这之前一共存在i*(i+1)/2种情况 i(i+1)/2
k 所以只要找到小于等于k的最大值 k
2 b k i ( i + 1 ) / 2 然后再把第2个b左移k-i*(i+1)/2位就可以了 2bki(i+1)/2

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        ll n,k;
        cin>>n>>k;
        ll i;
        for(i=1;i<=n;i++)
            if(i*(i+1)/2>=k)break;
        i--;
        ll t=i*(i+1)/2;
        ll x=k-t-1;
        i++;
        for(int j=1;j<=n;j++){
            if(j==n-i||j==n-x)cout<<'b';
            else cout<<'a';
        }
        cout<<endl;
    }
    return 0;
}


C. Ternary XOR

题意
c = a b 假设存在一种符号⊙如果c=a⊙b c=ab
c i = ( a i + b i ) % 3 那么c_i=(a_i+b_i)\%3 ci=(ai+bi)%3
c i , a i , b i 其中c_i,a_i,b_i表示三个数中的每一位 ci,ai,bi
n a b x 给定数的长度n和a⊙b的结果x nabx
a , b 使 m a x ( a , b ) 让你求得a,b并且需要使得max(a,b)最小 a,b使max(a,b)
题解
循环每一位
2 a b 1 如果是2,a和b各自得到一个1 2ab1
0 a b 0 如果是0,a和b各自该位为0 0ab0
1 退 1 a b 如果是1,退出循环,并把1给a,然后剩下所有数都给b 1退1ab

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        int n;string s;
        cin>>n>>s;
        string a,b;
        int i;
        for(i=0;i<n;i++){
            if(s[i]=='2'){
                a+='1';
                b+='1';
            }
            else if(s[i]=='0'){
                a+='0';
                b+='0';
            }
            else break;
        }
        if(i<n){
            a+=s[i];
            b+='0';
        }
        for(i++;i<n;i++){
            a+='0';
            b+=s[i];
        }
        cout<<a<<endl<<b<<endl;
    }
    return 0;
}

D. Carousel

题意
给一个环,环每个点有一种动物
要求给动物上色,相邻的不同的动物不能上相同的颜色
题解
如果只有一种动物,全部上一种颜色
如果有两种,两种动物各上一种颜色,一共两种
n 如果大于两种,首先判断n奇偶性 n
1212 1212 如果为偶数,按1212……1212排即可,两种颜色 12121212
1212 如果为奇数,再按1212排就会出现首尾相同,但是如果首尾的动物是不同的就会出现非法情况 1212
使 使 所以此时就在序列中找是否有连续相同的动物,\\在这个位置连续使用一个颜色两次,\\就可以使得首尾的颜色不相同,这样总共为两种颜色 使使
12 3 如果找不道连续相同的动物,那么就是三种颜色,按12排列把最后一个改成3即可 123

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int a[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        set<int> s;
        for(int i=1;i<=n;i++){cin>>a[i];s.insert(a[i]);}
        if(s.size()==1){
            cout<<1<<endl;
            for(int i=1;i<=n;i++)
                cout<<1<<' ';
            cout<<endl;
            continue;
        }
        if(s.size()==2){
            vector<int> v;
            cout<<2<<endl;
            for(auto i:s)v.pb(i);
            for(int i=1;i<=n;i++)
                if(a[i]==v[0])cout<<1<<' ';
                else cout<<2<<' ';
            cout<<endl;
            continue;
        }
        if(n%2==0||a[n]==a[1]){
            cout<<2<<endl;
            for(int i=1;i<=n;i++)
                if(i&1)cout<<1<<' ';
                else cout<<2<<' ';
            cout<<endl;
        }
        else{
            int i;
            for(i=2;i<=n;i++)
                if(a[i]==a[i-1])break;
            if(i>n){
                cout<<3<<endl;
                for(int i=1;i<n;i++)
                    if(i&1)cout<<1<<' ';
                    else cout<<2<<' ';
                cout<<3<<endl;
            }
            else{
                cout<<2<<endl;
                int cnt=1;
                for(int j=1;j<=n;j++){
                    if(j==i)cnt^=1;
                    if(cnt)cout<<1<<' ';
                    else cout<<2<<' ';
                    cnt^=1;
                }
                cout<<endl;
            }
        }
    }
    return 0;
}


E. Tree Queries

题意
m 给一棵树,然后有m次询问 m
k 每次询问给出k个点,问是否能找到一条从根出发的简单路径 k
1 包含这些点或者这些点到这个路径的距离为1 1
题解
想找到非法情况,肯定是因为有两个点他们最近根的两棵子树上并且都不是这个根的直接子节点
L C A l c a 1 所以直接采用LCA,从最深点开始找,两个点到他俩lca的距离是否出现同时大于1的情况 LCAlca1
N O Y E S 如果有则NO,否则输出YES NOYES

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

int a[maxn];
int n,depth[maxn], f[maxn][50];
int from[maxn], to[maxn << 1], nxt[maxn << 1], cnt,Log[maxn];
//链式前向星加边
void addEdge (int u, int v) {
    to[++cnt] = v, nxt[cnt] = from[u], from[u] = cnt;
}
//计算深度&计算祖先
void dfs (int u, int fa) {
    depth[u] = depth[fa] + 1;
    for (register int i = 1; i <= Log[n]; ++i) {
        if ((1 << i) > depth[u]) break;
        f[u][i] =  f[f[u][i - 1]][i - 1];
    }
    for (register int i = from[u]; i; i = nxt[i]) {
        ll v = to[i];
        if (v == fa) continue;
        f[v][0] = u;
        dfs (v, u);
    }
}
//计算LCA
inline int LCA (int x, int y) {
    if (depth[x] < depth[y]) swap(x, y);
    //我们默认x为更深的那个点
    for(register int i = Log[n] ; i >= 0 ; --i)
		if(depth[x] - (1 << i) >= depth[y]) x = f[x][i];
    //将x跳到和y同一深度上
    if (x == y) return x;
    for (register int i = Log[n]; i >= 0; --i)
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    //一起向上跳
    return f[x][0];
    //不难看出,此时两个点均在其LCA的下方,往上跳一次即可
}
void init(){
	Log[0] = -1;
    for (register int i = 1, u, v; i < n; ++i) {
        cin>>u>>v;
        addEdge (u, v); addEdge(v, u);
        Log[i] = Log[i >> 1] + 1;
    }
    Log[n] = Log[n >> 1] + 1;
}
int dis(int p , int q){return depth[p] + depth[q] - 2 * depth[LCA(p , q)];}
bool cmp(int a,int b){
    return depth[a]>depth[b];
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int m;
    cin>>n>>m;
    init();dfs(1,0);
    while(m--){
        int k;
        cin>>k;
        for(int i=1;i<=k;i++)cin>>a[i];
        sort(a+1,a+1+k,cmp);
        bool f=0;
        for(int i=2;i<=k;i++){
            int r=LCA(a[i],a[i-1]);
            if(dis(r,a[i-1])>1&&dis(r,a[i])>1){f=1;break;}
        }
        if(f)cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}


F. Make k Equal

题意
n 给定长度为n的数组 n
使 每次可以使最大数加一,或者最小数减一 使
k 问最少多少次操作可以获得k个相等的数 k
题解
首先将数组排序,计算出前缀和后缀和
k a i 然后循环判断找出变成k个a_i所需要的次数,取最小 kai
k 1 对于每个数,如果他的左边或者右边有k-1个数 k1
a i 1 使 如果是左边让所有数变成a_i-1,使用前缀和计算次数 ai1使
a i + 1 使 如果是右边让所有数变成a_i+1,使用后缀和计算次数 ai+1使
k 1 , a i + 1 a i 1 然后加上k-1,也就是把他们变成a_i+1或a_i-1次数 k1,ai+1ai1
a i 1 , a i + 1 如果两边都不够,就把左边全部变成a_i-1,右边a_i+1 ai1,ai+1
使 k 1 同时使用前缀和后缀和计算次数,然后加上k-1 使k1
0 最后在这些里取最小,为了排除直接有相等的情况,如果这个值小于0,那么就变零 0

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

ll a[maxn],s1[maxn],s2[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ll n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    sort(a+1,a+1+n);
    int cnt=1;
    for(int i=1;i<=n;i++){
        s1[i]=s1[i-1]+a[i];
        if(a[i]==a[i-1])cnt++;
        else cnt=1;
        if(cnt>=k){cout<<0<<endl;return 0;}
    }
    for(int i=n;i>=1;i--)
        s2[i]=s2[i+1]+a[i];
    ll ans=inf*inf;
    for(int i=1;i<=n;i++){
        ll tmp=inf*inf;
        if(i>=k)tmp=min(tmp,(a[i]-1)*(i-1)-s1[i-1]+k-1);
        if(n-i+1>=k)
            tmp=min(tmp,s2[i+1]-(a[i]+1)*(n-i)+k-1);
        if(i<k&&n-i+1<k){
            tmp=(a[i]-1)*(i-1)-s1[i]+s2[i]-(a[i]+1)*(n-i)+k-1;
        }
        if(tmp<0)tmp=0;
        ans=min(ans,tmp);
    }
    cout<<ans<<endl;
    return 0;
}

全部评论

相关推荐

点赞 评论 收藏
分享
09-29 17:44
已编辑
蔚来_测(准入职员工)
//鲨鱼辣椒:见不了了我实习了四个月上周再投筛选了一天就给我挂了
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务