廢話
前期題過得還是有點慢
題解
A
直接數出余數的補就好
#include <bits/stdc++.h>
using namespace std;
int a,b,t;
signed main() {
    cin>>t;
    while(t--) {
        cin>>a>>b;
        cout<<(b-a%b)%b<<endl;
    }
}
 
        B
給這些串分個類,很容易發現沒類的個數依次是 \(1,2,3,\dots\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
int t,n,k;
signed main() {
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--) {
        cin>>n>>k;
        int pos=1;
        while(k>pos) k-=pos, ++pos;
        ++pos;
        int q=k;
        for(int i=n;i>=1;--i) cout<<((i==pos||i==q)?'b':'a');
        cout<<endl;
    }
}
 
        C
從第一個 \(1\) 之后,將所有的數字倒到另一邊
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
char c[N],a[N],b[N];
int t,n;
signed main() {
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--) {
        cin>>n>>c+1;
        int fg=0;
        for(int i=1;i<=n;i++) {
            if(fg==0) {
                if(c[i]=='1') {
                    a[i]='1';
                    b[i]='0';
                    fg=1;
                }
                else if(c[i]=='2') {
                    a[i]='1';
                    b[i]='1';
                }
                else {
                    a[i]='0';
                    b[i]='0';
                }
            }
            else {
                a[i]='0';
                b[i]=c[i];
            }
        }
        for(int i=1;i<=n;i++) cout<<a[i];
        cout<<endl;
        for(int i=1;i<=n;i++) cout<<b[i];
        cout<<endl;
    }
}
 
         
         
        D
如果能二分圖染色就輸出顏色數,否則就輸出 \(3\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 400005;
int q,n,a[N],c[N],fail;
vector <int> g[N];
void dfs(int p) {
    for(int q:g[p]) {
        if(c[q]) {
            if(c[q]==c[p]) fail=1;
        }
        else {
            c[q]=3-c[p];
            dfs(q);
        }
    }
}
signed main() {
    ios::sync_with_stdio(false);
    cin>>q;
    while(q--) {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        int fg=0;
        for(int i=1;i<n;i++) if(a[i]!=a[i+1]) fg=1;
        if(a[1]!=a[n]) fg=1;
        if(fg==0) {
            cout<<1<<endl;
            for(int i=1;i<=n;i++) cout<<1<<" ";
            cout<<endl;
            continue;
        }
        for(int i=1;i<n;i++) if(a[i]!=a[i+1]) {
            g[i].push_back(i+1);
            g[i+1].push_back(i);
        }
        if(a[1]!=a[n]) {
            g[1].push_back(n);
            g[n].push_back(1);
        }
        fail=0;
        for(int i=1;i<=n;i++) if(c[i]==0) {
            c[i]=1;
            dfs(i);
        }
        if(fail) {
            cout<<3<<endl;
            for(int i=1;i<n;i++) cout<<(i%2)+1<<" ";
            cout<<3<<endl;
        }
        else {
            cout<<2<<endl;
            for(int i=1;i<=n;i++) cout<<c[i]<<" ";
            cout<<endl;
        }
        for(int i=1;i<=n;i++) {
            a[i]=c[i]=0;
            g[i].clear();
        }
    }
}
 
        E
給定一棵有根樹,每次詢問給定一個點集,問是否存在根到某點的鏈,使得點集中所有點到鏈的距離不大於 \(1\)。
將每次詢問的結點按深度排序好,相鄰的兩個結點 \(p,q\) 一定滿足 \(d[p]-d[lca] \le 1 \or d[q]-d[lca] \le 1\),其中 \(lca=lca(p,q)\)
必要性顯然,充分性考慮讓毛毛蟲的莖一直往差值大的那邊走即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
vector <int> g[N];
int n,m,t1,t2,t3,dep[N],fa[N][20];
void dfs(int p) {
    for(int q:g[p]) {
        if(dep[q]) continue;
        dep[q]=dep[p]+1;
        fa[q][0]=p;
        dfs(q);
    }
}
int lca(int p,int q) {
    if(dep[p]<dep[q]) swap(p,q);
    for(int i=18;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
    for(int i=18;i>=0;--i) if(fa[p][i]-fa[q][i]) p=fa[p][i],q=fa[q][i];
    if(p-q) return fa[p][0];
    else return p;
}
bool cmp(const int &p,const int &q) {
    return dep[p]<dep[q];
}
signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<n;i++) {
        cin>>t1>>t2;
        g[t1].push_back(t2);
        g[t2].push_back(t1);
    }
    dep[1]=1;
    dfs(1);
    for(int i=1;i<=18;i++) {
        for(int j=1;j<=n;j++) {
            fa[j][i]=fa[fa[j][i-1]][i-1];
        }
    }
    for(int i=1;i<=m;i++) {
        int k;
        cin>>k;
        vector <int> vec;
        for(int j=0;j<k;j++) {
            int t;
            cin>>t;
            vec.push_back(t);
        }
        sort(vec.begin(),vec.end(),cmp);
        int fg=1;
        for(int j=1;j<k;j++) {
            int p=vec[j],q=vec[j-1];
            int l=lca(p,q);
            if(dep[p]-dep[l]>1 && dep[q]-dep[l]>1) fg=0;
        }
        cout<<(fg?"YES":"NO")<<endl;
    }
}
 
        F
枚舉選擇一個中間點,計算把邊上壓到中間這條線上的答案
壓的時候要考慮兩邊壓和單邊壓的情況
(以下代碼中的二分顯得很累贅,純粹為了偷懶而出現)
using namespace std;
#define int long long
const int N = 200005;
int n,k,a[N],pre[N],suf[N],ans=1e18;
map<int,int> mp;
signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) {
        pre[i]=pre[i-1]+a[i];
    }
    for(int i=n;i>=1;--i) {
        suf[i]=suf[i+1]+a[i];
    }
    for(int i=1;i<=n;i++) mp[a[i]]++;
    for(auto i:mp) if(i.second>=k) {
        cout<<0<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++) {
        int x=a[i];
        int e=upper_bound(a+1,a+n+1,x)-lower_bound(a+1,a+n+1,x);
        int g=n-(upper_bound(a+1,a+n+1,x)-a)+1;
        int l=lower_bound(a+1,a+n+1,x)-a-1;
        int sg=suf[n-g+1];
        int sl=pre[l];
        int tmp=sg-g*x+l*x-sl-(n-k);
        ans=min(ans,tmp);
        if(n-l>=k) {
            int tx=sg-g*x-(n-l-k);
            ans=min(ans,tx);
        }
        if(n-g>=k) {
            int tx=l*x-sl-(n-g-k);
            ans=min(ans,tx);
        }
        //cout<<l<<" "<<e<<" "<<g<<endl;
    }
    cout<<max(0ll,ans);
}
 
       