SDUT 2021 Summer Individual Contest - 5(for 20)

SDUT 2021 Summer Individual Contest - 5

C - Bacteria

大意:n堆细胞,大小分别为a[i]。当且仅当两个细胞堆相同大小,可以合并为一个两倍大小的细胞堆。现可以添加任意大小的任意个细胞堆,如果最终可以合并为一个堆,输出需要添加的细胞堆数,否则输出-1。

思路:(它好像一个二叉树鸭)

  1. 最终可以合并的条件是:任意一个值都是最小值的2^n(n=0,1,2…)倍。
  2. 这里要用到小根堆的优先队列,去完成合并成一个值的操作:取出队首的两个值x,y(x <= y)如果两个值相等,完成合并,将2x入队;否则x=x2,直到x == y,每执行一次循环,说明需要添加一堆,则答案自增1。
/*
 * @Description: 
 * @Author: Kirie
 * @LastEditTime: 2021-08-09 16:21:42
 */
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <strin
#include <queue>
#include <deque>
#include <stack>
#include <iomanip>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define bug cout << "BUG HERE\n"
#define debug(x) cout << #x << " = " << x << endl
#define ll long long
typedef pair<int, int> PII;

const int INF = 0x3f3f3f3f;
const int N = 1e6 + 7;

priority_queue<ll, vector<ll>, greater<ll> > q; // 小根堆优先队列

bool check(ll num) {
    ll now = 1;
    while(now <= num) {
        //debug(now);
        if(num == now) {
            return true;
        }
        now *= 2;
    }
    return false;
}

ll a[N];

int main()
{
    ll n, mn = INF;
    cin >> n;
    rep(i,1,n) {
        cin >> a[i];
        mn = min(mn, a[i]);
        q.push(a[i]);
    }
    int flag = 1;
    rep(i,1,n) {
        if( (a[i] % mn == 0) && check(a[i] / mn) ) {
            continue; 
        } else {
            flag = 0;
            break;
        }
    }
    ll ans = 0;
    if(flag)
    while(q.size()) {
        //debug(q.top());
        ll x = q.top();
        q.pop();
        ll y = q.top();
        q.pop();
        while(x != y) {
            x *= 2;
            ans ++; 
        }
        q.push(x * 2);
    }
    if(flag) 
        cout << ans << endl;
    else 
        cout << -1 << endl;
    return 0;
}

F - Tickets

大意:对于一个有前导0的6位数,我们称其幸运值为前三位数字之和减去后三位数字之和的绝对值(如123456的幸运值为|1+2+3-4-5-6|=9)。现给出一个数n,求从数字0~n-1中幸运值小于n的数的个数。
思路:该题如果每次读入都求一遍,时间复杂度(O(1e6*2e5))会爆。需要进行一次预处理,之后每次读入输出就很简单了(1e6+2e5)。建议通过函数压缩代码量。

/*
 * @Description: 
 * @Author: Kirie
 * @LastEditTime: 2021-08-09 20:06:08
 */
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <iomanip>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define bug cout << "BUG HERE\n"
#define debug(x) cout << #x << " = " << x << endl
#define ll long long
typedef pair<int, int> PII;

const int INF = 0x3f3f3f3f;
const int N = 1e6 + 7;

int a[N];// * i的幸运值
int b[N]; // * 编号小于i & 幸运值小于a[i] 的和
int st[30]; // * 目前为止幸运值为i的数的个数

int sum(int num ) {
    return num / 100 + num / 10 % 10 + num % 10;
}

int cal(int num) {
    int a = sum(num / 1000);
    int b = sum(num % 1000);
    return abs(a - b);
}

void init() {
    rep(i,0,N) {
        a[i] = cal(i);
        st[a[i]] ++;
        for(int j = 0; j<a[i]; j++) {
            b[i] += st[j];
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    init();
    int n;
    cin >> n;
    int x;
    rep(i,0,n-1) {
        cin >> x ;
        cout << b[x] << endl;
    }
    return 0;
}

H - Theater Square

大意:广场大小为n行 * m列,中间(x1,y1)到(x2,y2)的矩形需要空出。现需要铺2 * 1的长砖,要求为横铺,如果摆不下则需要将一块2 * 1的砖拆为1 * 1的小砖补全,问最小要拆多少块。
思路:

  1. 依据空地位置可以划分为四个区域。

    在这里插入图片描述

  2. 对于每个a列b行的区域,如果他的列数a为奇数,则需要b块小砖,否则可以铺满,不需要拆砖。

    在这里插入图片描述

  3. 总共需要sum块小砖,则需要sum/2块长砖,如果余下一块需要补全。

/*
 * @Description: 
 * @Author: Kirie
 * @LastEditTime: 2021-08-09 14:17:43
 */
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <iomanip>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define bug cout << "BUG HERE\n"
#define debug(x) cout << #x << " = " << x << endl
#define ll long long
typedef pair<int, int> PII;

const int INF = 0x3f3f3f3f;
const int N = 2e5 + 7;

int cal (int a, int b) { // 一行a个格,一列b个格(列数,行数)
    return a % 2 ? b : 0;
}

int main()
{
    int n, m;
    cin >> n >> m;
    int x1, x2, y1, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    int a = cal(m,x1-1);
    int b = cal(m,n-x2);
    int c = cal(y1-1,x2-x1+1);
    int d = cal(m-y2,x2-x1+1);
    int res = a+ b + c + d;
    if(res % 2) cout << res / 2 + 1 << endl;
    else cout << res / 2 << endl;
    return 0;
}

I - Heist

大意:n个数,求其中不连续的缺少的数的个数。

/*
 * @Description: 
 * @Author: Kirie
 * @LastEditTime: 2021-08-09 13:08:17
 */
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <iomanip>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define bug cout << "BUG HERE\n"
#define debug(x) cout << #x << " = " << x << endl
#define ll long long
typedef pair<int, int> PII;

const int INF = 0x3f3f3f3f;
const int N = 1e3 + 7;

int main()
{
    int n;
    int mx = 0, mn = INF;
    int x;
    cin >> n;
    rep(i,1,n) {
        cin >> x;
        mx = max(mx,x);
        mn = min(mn,x);
    }
    cout << mx - mn - n + 1 << endl;
    return 0;
}

J - Buying a TV Set

大意:求符合下列条件的尺寸的个数:长宽分别不超过a,b,长宽比例为x/y。
思路:让x和y分别除以它们的最大公倍数,再让长和宽的上限分别整除x和y,其中的最小值即符合条件的个数。

/*
 * @Description: 
 * @Author: Kirie
 * @LastEditTime: 2021-08-09 13:18:36
 */
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <iomanip>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define bug cout << "BUG HERE\n"
#define debug(x) cout << #x << " = " << x << endl
#define ll long long
typedef pair<int, int> PII;

const int INF = 0x3f3f3f3f;
const int N = 1e3 + 7;

ll gcd(ll a,ll b) {
    if(a % b == 0) return b;
    else return gcd(b, a % b);
}

int main()
{
    ll a, b, x, y;
    cin >> a >> b >> x >> y;
    ll g = gcd(x, y);
    x /= g;
    y /= g;
    a /= x;
    b /= y;
    cout << min(a,b) << endl;
    return 0;
}

K - Medians and Partition

大意:对于一串数,对其划分数组,确保每个数组的中位数都大于等于m,问最大能划分多少。

/*
 * @Description: 
 * @Author: Kirie
 * @LastEditTime: 2021-08-09 16:28:17
 */
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <iomanip>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define bug cout << "BUG HERE\n"
#define debug(x) cout << #x << " = " << x << endl
#define ll long long
typedef pair<int, int> PII;

const int INF = 0x3f3f3f3f;
const int N = 1e6 + 7;

int main()
{
    int n, m, x;
    cin >> n >> m;
    int ans = 0, res = 0;
    for(int i=0;i<n;i++) {
        cin >> x;
        if(x < m) ans ++;
        else res ++;
    }
    cout << max(0, res - ans) << endl;
    return 0;
}

/*
 *
 ?                        _oo0oo_
 !                       o8888888o
 ?                       88" . "88
 !                       (| = = |)
 ?                       0\  √ /0
 !                     ___/`---'\___
 ?                   .' \\|     |// '.
 !                  / \\|||  :  |||// \
 ?                 / _||||| -:- |||||- \
 !                |   | \\\  - /// |   |
 ?                | \_|  ''\---/''  |_/ |
 !                \  .-\__  '-'  ___/-. /
 ?              ___'. .'  /--.--\  `. .'___
 !           ."" '<  `.___\_<★>_/___.' >' "".
 ?          | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 !          \  \ `_.   \_ __\ /__ _/   .-` /  /
 ?      =====`-.____`.___ \_____/___.-`___.-'=====
 !                        `=---='
 ? 
 * 
//                                                      
 * 
 todo   佛祖保佑 = 永不宕机 && 永无BUG && 永葆发量 = true
 */
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值