Codeforces Round #694 (Div. 2) A~D + F 题解

A. Strange Partition

  • 解题思路
    求最大值易知,就是每个元素向上取整求和即可。对于最小值,我们需要减少向上取整的次数,即最大化利用整除,这一步我们可以将所有的余数都加起来,最后再进行向上取整。

  • AC代码

/**
  *@filename:A_Strange_Partition
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-02 19:08
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;

int t,n,x;
int a[N];
void solve(){
    ll ans1 = 0,ans2 = 0,temp = 0;
    for(int i = 1; i <= n; ++ i){
        ans1 += a[i] / x;
        ans2 += a[i] / x + (a[i] % x != 0);
        temp +=(a[i] % x);
    }
    cout << ans1 + temp / x + (temp % x != 0) << " " << ans2 << endl;
}
int main(){
    scanf("%d", &t);
    while(t -- ){
        scanf("%d%d", &n , &x);
        for(int i = 1; i <= n; ++ i){
            scanf("%d", &a[i]);
        }
        solve();
    }
    return 0;
}

B. Strange List

  • 解题思路
    一道模拟题,我们注意,模拟时需要将相同的数一起处理。所以我们可以用pair对来存储其值和连续出现次数,用队列来模拟。注意,一但有不合法数据,机器会立即停止运作。所以我们需要设置标志变量来判断,以及时退出。

  • AC代码

/**
  *@filename:B_Strange_List
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-02 19:13
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int N = 100000 + 5;
const int P = 1e9+7;

int t,n,x;
queue<pii> q;
void solve(){
    ll ans = 0;
    pii head;
    bool flag = true;//机器运作标志。
    while(!q.empty()){
        head = q.front();
        q.pop();
        ans += 1LL * head.first * head.second;
        if(head.first % x != 0)flag = false;
        if(flag){
            q.push({head.first / x , head.second * x});
        }
        //cout << head.first << " " << head.second << endl;
    }
    printf("%lld\n",ans);
}
int main(){
    scanf("%d", &t);
    while(t -- ){ 
        scanf("%d%d", &n, &x);
        int temp;
        while(!q.empty())q.pop();
        for(int i = 1; i <= n; ++ i){
            scanf("%d",&temp);
            q.push({temp,1});
        }
        solve();
    }
    return 0;
}

C. Strange Birthday Party

  • 解题思路
    贪心题。对于每个人标注的 k k k,如果其越大,那么可供的选择也就越多,而对于花费 c c c序列也是递增的,所以我们可以先处理 k k k标注大的,这样总能保证我们将最小的 c c c选掉,得到最优解。

  • AC代码

/**
  *@filename:C_Strange_Birthday_Party
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-02 20:36
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 300000 + 5;
const int P = 1e9+7;

int t,n,m,k[N],c[N];
void solve(){
    sort(k + 1 ,k + 1 + n,greater<int>());
    int d = 1;
    ll sum = 0;
    for(int i = 1; i <= n; ++ i){
        if(k[i] >= d)sum += c[d ++ ];
        else sum += c[k[i]];
    }
    cout << sum << endl;
}
int main(){
    scanf("%d", &t);
    while(t -- ){
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++ i){
            scanf("%d", &k[i]);
        }
        for(int i = 1; i <= m; ++ i){
            scanf("%d", &c[i]);
        }
        solve();
    }
    return 0;
}

D. Strange Definition

  • 解题思路
    我们先来解释一下相邻,如果 ( x , y ) (x,y) (x,y)满足 l c m ( x , y ) g c d ( x , y ) \frac{lcm(x,y)}{gcd(x,y)} gcd(x,y)lcm(x,y)得到的结果是可以开平方的,则说明 ( x , y ) (x,y) (x,y)相邻。我们对这个式子做一下变换,即因为 l c m ( x , y ) = x y g c d ( x , y ) lcm(x,y)=\frac{xy}{gcd(x,y)} lcm(x,y)=gcd(x,y)xy,所以 l c m ( x , y ) g c d ( x , y ) = x y g c d ( x , y ) 2 \frac{lcm(x,y)}{gcd(x,y)}=\frac{xy}{gcd(x,y)^2} gcd(x,y)lcm(x,y)=gcd(x,y)2xy。则表明如果 x , y x,y x,y相乘是一个完全平方数,则说明 x , y x,y x,y相邻,易知相邻具有传递性。
    每经过一秒,相邻的元素 x x x会被其所有相邻元素的乘积代替掉(包括它本身),即倘若 x , y , z x,y,z x,y,z相邻,那么经过一秒后 x , y , z x,y,z x,y,z均会变成 x × y × z x\times y\times z x×y×z。所以我们可以相邻的元素分组,分完组后,组别中如果只有奇数个元素,那么它是不会变的,因为它的指数还是奇数,而组别中如果有偶数个元素,那么经过一秒后它们会成为一组,即只存在一组偶数个元素的组别,因为经过这次元素的指数都是偶数。所以我们关键就是利用质因数分解来分组,对于偶数次,我们不关心,我们主要是要存储奇次质因子。这可以利用map实现。然后,求 m a x d max_d maxd时,对于 0 0 0秒的时候,正常获取每个组别的最大元素数量即可,而对于 1 1 1秒及之后的,我们需要将偶数元素的组合并,然后与奇数次的比较得到最大值即可。
  • AC代码
/**
  *@filename:D_Strange_Definition
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-03 09:20
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 300000 + 5;
const int P = 1e9+7;

int t,n,q;
ll w;
int primer[N],cnt;
map<int,int> p;//存储质因子。
void init(){
    for(int i = 2; i < N; ++ i){
        if(!primer[i]){
            primer[++primer[0]] = i;
            for(int j = i * 2; j < N; j += i){
                primer[j] = 1;
            }
        }
    }
}
void get(int x){
    int ans = 1;
    for(int i = 1; i <= primer[0]; ++ i){
        int temp = 0;
        while(x % primer[i] == 0){
            temp++;
            x /= primer[i];
        }
        if(temp % 2 == 1){
            ans *= primer[i];//获取奇质因子。对于偶数因子本来就满足,无需考虑。
        }
        if(x < 1LL * primer[i] * primer[i])break;
    }
    if(x != 1){
        ans *= x;
    }
    p[ans] ++;
}
void solve(){
    int ans1 = 0,ans2 = 0;
    for(auto &it: p){
        ans1 = max(ans1,it.second);
        if(it.second % 2 == 0)ans2 += it.second;
        else if(it.first == 1) ans2 += it.second;//将偶数因子累加起来。
    }
    ans2 = max(ans1,ans2);
    scanf("%d", &q);
    while(q -- ){
        scanf("%lld", &w);
        printf("%d\n",w ? ans2 : ans1);
    }
}
int main(){
    init();
    scanf("%d", &t);
    while(t -- ){
        scanf("%d", &n);
        p.clear();
        int temp;
        for(int i = 1; i <= n; ++ i){
            scanf("%d", &temp);
            get(temp);
        }
        solve();
    }
    return 0;
}

F. Strange Housing

  • 解题思路
    就是一个染色问题。题目中要求任意房屋都可通行,且一条边上只能有一端住老师。对于这种问题,我们知道如果图连通,则必定有且,这根据染色思想可得。那么,我们怎么去放置呢?我们的思路就是遍历所有点,如果当前节点没有染色,且相邻的所有节点都没有染色,就染色。否则不染色。
    这样,即可实现题目需求。

  • AC代码

/**
  *@filename:F_Strange_Housing
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-03 11:09
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 600000 + 5;
const int P = 1e9+7;

int t,n,m,u,v;
struct node{
    int to,next;
}edges[N];
bool vis[N],flag[N];//vis[i]表示i节点是否已经访问过,flag[i]表示i节点是否已经染色。
int head[N],tot;
void init(){
    for(int i = 1; i <= n; ++ i){
        vis[i] = false;
        flag[i] = false;
        head[i] = false;
    }
    tot = 0;
}
void add(int u,int v){
    edges[++tot].to = v;
    edges[tot].next = head[u];
    head[u] = tot;
}
bool check(){
    //检查图是否连通。以1作为起点,判断是否能访问到n个顶点。
    int num = 1;
    queue<int> q;
    q.push(1);
    vis[1] = true;
    while(!q.empty()){
        int idx = q.front();
        q.pop();
        for(int i = head[idx]; i; i = edges[i].next){
            if(!vis[edges[i].to]){
                vis[edges[i].to] = true;
                num ++;
                q.push(edges[i].to);
            }
        }
    }
    return num == n;
}
void solve(){
    if(!check()){
        puts("NO");
    }
    else{
        //否则一定连通。
        puts("YES");
        queue<int> q;
        q.push(1);
        for(int i = 1; i <= n; ++ i){
            vis[i] = false;
        }
        vis[1] = true;
        int res = 0;
        while(!q.empty()){
            int idx = q.front();
            q.pop();
            bool flag1 = false;
            for(int i = head[idx]; i; i = edges[i].next){
                if(!vis[edges[i].to]){
                    vis[edges[i].to] = true;
                    q.push(edges[i].to);
                }
                //检查相邻顶点是否染色。
                if(flag[edges[i].to]){
                    flag1 = true;
                }
            }
            //检查是否有必要染色。
            if(!flag1){
                flag[idx] = true;
                res ++;
            }
        }
        printf("%d\n",res);
        for(int i = 1; i <= n; ++ i){
            if(flag[i]){
                printf("%d ",i);
            }
        }
        printf("\n");
    }
}
int main(){
    scanf("%d", &t);
    while(t -- ){
        init();
        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; ++ i){
            scanf("%d%d", &u, &v);
            add(u,v);
            add(v,u);
        }
        solve();
    }
    return 0;
}
posted @   unique_pursuit  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示