暑期算法训练13 - 蓝桥杯算法双周赛第17场题解(CDF)

本场A太弱智,BE考察思维,但是都比较容易想到,这里就不写这三题的题解了,主要写一下CDF三题的做法和思路。

本场比赛链接放在这里——第 17 场蓝桥算法赛

目录

C题题面

思路分析

代码实现

D题题面

思路分析

代码实现

F题题面

思路分析

代码实现


C题题面

思路分析

按题意,我们寻找最多能挑选出的单独来自不同城池的猛将数量,首先我们可以开一个map记录一下不同城池里猛将的数量,map的长度表示城池的数量。但是要从小到大排序,map先转换为数组cnt[],方便排序和遍历。如果k小于等于mp.size()则直接输出k即可,因为此时一人一个城池情况下,数量刚刚好或者用不完。否则,我们可根据贪心思想,每次把(k  -  mp.size())放进容纳人数最多的城池里,这样就能得到题意中“所叙述的最多城池数量”,当剩余数小于等于0时,我们把答案输出。

代码实现

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <iomanip>
#include <climits>
#define int long long 
#define x first 
#define y second 
using namespace std ;
typedef pair<int,int> PII;
const int N = 1e5 + 10;
int a[N];
vector<int> cnt;
PII p[N];
map<int,int> mp;
void solve()
{
     int n,k;
     cin >> n >> k;
     for(int i = 1; i <= n; i++) cin >> a[i];
     for(int i = 1; i <= n; i++) mp[a[i]] ++;
     for(auto &c : mp)  cnt.push_back(c.y);
     sort(cnt.begin() , cnt.end() , greater<int>());//从大到小排序
     int ans = 0;
     if(k <= mp.size()) 
     {
         cout << k << endl;
         return;
     }
     else  
     {
        int v = k - mp.size();//k多出城池数量的部分
        for(int i = 0; i < mp.size(); i++)
        {
            v = v + 1 - cnt[i];
            if(v <= 0)
            {
                cout << mp.size() - i - 1 << endl;
                return;
            }
        }
     }

}
signed main()
{
     ios::sync_with_stdio(false);
     cin.tie(nullptr),cout.tie(nullptr);
     int t  = 1 ;
     // cin >> t;
     while(t -- ) solve();
     return 0;
}

D题题面

思路分析

这个题意其实非常容易理解,也是个思维题,找对规律即可,如果x >= y * k,则直接减掉输出即可,如果x < y*k且 y > x 时,做奇数次询问结果为abs(x -  y),偶数次询问结果就为x,但如果x < y*k且 y < x 时我们先把操作进行到 y > x然后再按规律正常输出——

代码实现

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <iomanip>
#include <climits>
#define int long long 
#define x first 
#define y second 
#define ct cout
using namespace std ;
typedef pair<int,int> PII;
const int N = 1e5 + 10;
int a[N];
PII p[N];
void solve()
{
   int x,y,k;
   cin >> x >> y >> k;
   int ans = y * k;
   if(x >= ans)  ct << x - ans << endl;
   else  
   {
       int c = x / y;
       k -= c;
       x %= y;
       if(k % 2) ct << abs(x - y) << endl;
       else ct << x << endl;
   }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr),cout.tie(nullptr);
    int t ;
    cin >> t;
    while(t -- ) solve();
    return 0;
}

F题题面

思路分析

  质因数分解 + 快速幂

代码实现

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <iomanip>
#include <climits>
#define int long long 
#define x first 
#define y second 
using namespace std ;
typedef pair<int,int> PII;
const int N = 1e5 + 10;
const int mod = 998244353;
int a[N];
PII p[N];
int qmi(int a,int b,int p) //快速幂(求 a ^ b % p)
{
    int res = 1 % p;
    while(b)
    {
        if(b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
void solve()
{
     int n, m;
     cin >> n >> m;
     vector<int> arr;
     int x = m;
     for(int i = 2; i <= x /i; i++)
     {
        if(x % i == 0)
        {
            int s = 0;
            while(x % i == 0) x /= i,s++;
            arr.push_back(s);
        }
     }
     if(x > 1) arr.push_back(1);
     int res = 1;
     for(auto &c : arr)
     {
        int cnt = (qmi(c + 1,n,mod) - qmi(c,n,mod) + mod) % mod;// 16 - 9 = 7
        res = (res * cnt % mod) % mod; 
     }
     cout << res << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr),cout.tie(nullptr);
    int t  = 1;
    //cin >> t;
    while(t -- ) solve();
    return 0;
}

写到这实在太困了,没有休息好,睡觉去了www,明天补前几天打的牛客两场的题解——

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值