Codeforces Round 1027 (Div. 3) A-F

A. Square Year

判断一个数是不是平方数即可,赛时无脑写暴力了

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){   
    int s;
    cin>>s;

    for(int i=0;i<=100;i++){
        for(int j=i;j<=100;j++){
            if((i+j)*(i+j)==s){
                cout<<i<<" "<<j<<endl;
                return;
            }
            
        }
    }
    cout<<-1<<endl;
}   

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

B. Not Quite a Palindromic String

如果有k对相同的数配对,则需要有(n-k*2)/2对01配对,先配对这些,在再看剩下的能不能配够k对

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){   
    int n,k;
    cin>>n>>k;
    string s;
    int c0=0,c1=0;

    cin>>s;
    for(auto ch:s){
        if(ch=='0') c0++;
        else c1++;
    }

    int tar=(n-2*k)/2;
    if(c1<tar || c0<tar){
        cout<<"NO\n";
        return;
    }
    c0-=tar;
    c1-=tar;

    if(c1/2 + c0/2 == k){
        cout<<"YES\n";
    }
    else cout<<"NO\n";




}   

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

C. Need More Arrays

首先重复的元素是没用的,然后无脑dp就行了

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){   
    int n;
    cin>>n;
    vector<int> a(n+1);

    for(int i=1;i<=n;i++){
        cin>>a[i];
    }

    a.erase(unique(a.begin()+1,a.end()),a.end());

    int f[n+10][2];

    n=a.size()-1;

    f[1][1]=0;//删除第i个数,前i个数的最大值
    f[1][0]=1;//不删

    for(int i=2;i<=n;i++){

        f[i][0]=f[i-1][1]+1;
        f[i][1]=f[i-1][0];

        if(a[i]>a[i-1]+1){
            f[i][0]=max(f[i][0],f[i-1][0]+1);
        }
    }


    cout<<max(f[n][1],f[n][0])<<endl;


}   

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

D. Come a Little Closer

先把所有的点用矩形框住,要删除的点一定是矩形四个角的点。

维护x,y的最大值和次大值,枚举删除一个点后,剩余点的矩形的长和宽。注意可能此时矩形内部被填满了,要多开一行或一列

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){   
    int n;
    cin>>n;
    vector<int> x(n+1),y(n+1);
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
    }

    if(n==1){
        cout<<1<<endl;
        return;
    }

    auto tx=x,ty=y;
    sort(tx.begin()+1,tx.end());
    sort(ty.begin()+1,ty.end());

    int mn1x=tx[1],mn2x=tx[2];
    int mx1x=tx[n],mx2x=tx[n-1];
    int mn1y=ty[1],mn2y=ty[2];
    int mx1y=ty[n],mx2y=ty[n-1];

    int cntmnx=count(tx.begin()+1,tx.end(),mn1x);
    int cntmxx=count(tx.begin()+1,tx.end(),mx1x);
    int cntmny=count(ty.begin()+1,ty.end(),mn1y);
    int cntmxy=count(ty.begin()+1,ty.end(),mx1y);

    int ans=inf;
    for(int i=1;i<=n;i++){
        int lox=(x[i]==mn1x && cntmnx==1?mn2x:mn1x);
        int hix=(x[i]==mx1x && cntmxx==1?mx2x:mx1x);
        int loy=(y[i]==mn1y && cntmny==1?mn2y:mn1y);
        int hiy=(y[i]==mx1y && cntmxy==1?mx2y:mx1y);

        int dx=hix-lox+1;
        int dy=hiy-loy+1;
        int val=dx*dy;
        int nd=n-1;

        int tmp;
        if(val==nd) tmp=min((dx+1)*dy,dx*(dy+1));
        else tmp=val;

        ans=min(ans,tmp);
    }

    cout<<ans<<endl;
}


signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

E. Kirei Attacks the Estate

维护每个点的最大值和最小值,u的子节点v,v的最大值等于 w[v] - u 的最小值

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){   
    int n;
    cin>>n;

    vector<int> w(n+10),mn(n+10,inf),mx(n+10,-inf);
    vector<vector<int>> g(n+10);

    for(int i=1;i<=n;i++){
        cin>>w[i];
    }

    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    mn[0]=0;
    mx[0]=0;

    auto dfs = [&](auto dfs,int u,int pre)->void {
        mn[u] = min({mn[u], w[u], w[u] - mx[pre]});
        mx[u] = max({mx[u], w[u], w[u] - mn[pre]});

        for(auto v:g[u]){
            if(v==pre) continue;
            dfs(dfs,v,u);
        }
    };

    dfs(dfs,1,0);
    for(int i=1;i<=n;i++){
        cout<<mx[i]<<" ";
    }
    cout<<endl;
}   

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

F. Small Operations

x,y, 要先除掉 x 有 y 没有的因数,再乘上 y 有 x 没有的因数

设 t = gcd(x,y)

就是先除掉 x/t,再乘上 y/t

每次要找到,从1乘到 x/t 的最小合法乘法次数, 这一步可以在 x/t 的约数上dp得到

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
const int N=1e6;

/*
x,y, 要先除掉x有y没有的因数,再乘上y有x没有的因数
设 t = gcd(x,y)
就是先除掉x/t的因数,再乘上y/t的因数
每次要找到,从1乘到x/t的最小次数, 这一步用约数dp
*/

vector<vector<int>> g(N+10);//每个数的约数

void init(){
    for(int i=1;i<=N;i++){
        for(int j=i;j<=N;j+=i){
            g[j].push_back(i);
        }
    }
}

void solve(){   
    int x,y,k;
    cin>>x>>y>>k;

    if(k==1){
        if(x==y) cout<<0<<endl;
        else cout<<-1<<endl;
        return;
    }

    int t=__gcd(x,y);
    x/=t;
    y/=t;

    auto work=[&](int val)-> int {
        int n=g[val].size();
        vector<int> f(n,inf);
        f[0]=0;
        for(int i=0;i<n;i++){
            if(f[i]==inf) continue;
            for(int j=i+1;j<n;j++){
                if(g[val][j]%g[val][i]==0 && g[val][j]/g[val][i]<=k){
                    f[j]=min(f[j],f[i]+1);
                }
                if(g[val][j]/g[val][i]>k) break;
            }
        }
        return f[n-1];
    };

    int ans1=work(x);
    int ans2=work(y);

    if(ans1+ans2>inf/2){
        cout<<-1<<endl;
    }
    else{
        cout<<ans1+ans2<<endl;
    }
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    init();

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}
posted @ 2025-05-28 03:37  LYET  阅读(199)  评论(0)    收藏  举报