Codeforces Round #774 (Div. 2)

这几次比赛真的拉胯,我也不知道什么原因,也有可能是好久不写题解了吗,以前每次写完题目都会补一份自己的理解,也许是最近对题目的二次思考少了吗?也可能是学习方法不对,该加练了

A - Square Counting

题意

一个长度为n+1的数组,这个数组中的元素可以取值为 0 ≤ a i < n    o r    a i = n 2 0\leq a_i < n \;or\;a_i=n^2 0ai<norai=n2,使得这些数加起来最后为 s s s,问在这些数中有多少的数为 n 2 n^2 n2

题解

完善官方题解

我们模仿余数的定义写出这样一个方程: s = x ∗ n 2 + y s=x*n^2+y s=xn2+y,那么x就是我们想要的答案

题意给定了s一定成立,那么我们可以就类比出发,看看有几个 n 2 n^2 n2

那么 y ≤ ( n − 1 ) ∗ ( n + 1 ) = n 2 − 1 y\le(n - 1) * (n +1)=n^2-1 y(n1)(n+1)=n21,y代表剩下的数,剩下的数最多有 n + 1 n+1 n+1个,其中最大的元素取值为 n − 1 n-1 n1,那么最大可能的取值就是 n 2 − 1 n^2-1 n21

所以: ⌊ s n 2 ⌋ = ⌊ x ∗ n 2 + y n 2 ⌋ = ⌊ x + y n 2 ⌋ \left\lfloor\dfrac{s}{n^2}\right\rfloor=\left\lfloor\dfrac{x*n^2+y}{n^2}\right\rfloor=\left\lfloor x+ \dfrac{y}{n^2}\right\rfloor n2s=n2xn2+y=x+n2y

又因为 y ≤ ( n − 1 ) ∗ ( n + 1 ) = n 2 − 1 y\le(n - 1) * (n +1)=n^2-1 y(n1)(n+1)=n21

所以 ⌊ n 2 − 1 n 2 ⌋ = 0 \left\lfloor\dfrac{n^2-1}{n^2}\right\rfloor=0 n2n21=0

所以相除就是我们想要的结果

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
ll n, s;

void solve(){
    cin >> n >> s;
    cout << s / (n * n) << endl;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while(T--){
        solve();
    }
}

B - Quality vs Quantity

题意

讲一些数划为蓝的和红的,也可以不属于任何一方

问这个序列中能否找到这样一个序列,使得红方元素的和大于蓝方元素的和并且红方所选择的元素个数小于蓝方所选择的元素个数

题解

我们知道,让红方元素的和尽可能的大并且元素个数尽可能的少满足这个条件肯定是最好的

那么我们可以先从大到小排序(怎么排都行),先确定红方的初始元素为最大的元素,蓝方的元素为最小的两个元素,然后同时往中间,这样始终能保证题目的数量要求,并且由于两边都加一个数,且红方加的一定比蓝方的大,那么就是在缩小他们之间的距离,那么剩下的我们就枚举这些情况然后如果有满足条件的直接输出即可

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int n;
ll a[N * 2];
ll s[N * 2];

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

    sort(a + 1, a + 1 + n, greater<int>());

    ll sumr = a[1];
    ll sumb = a[n] + a[n - 1];

    if(sumr > sumb){
        cout << "YES" << Endl;
        re;
    }
    else{
        int r = 2;
        int b = n - 2;
        while(r < b){
            sumr += a[r];
            sumb += a[b];
            if(sumr > sumb){
                cout << "YES" << Endl;
                return;
            }
            r++, b--;
        }
    }

    cout << "NO" << endl;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while(T--){
        solve();
    }
}

C - Factorials and Powers of Two

题意

问一个数能否用最少的阶乘或者2幂指数来组合,问最少要几个数;选取的数不能相同

题解

在1e12范围下,阶乘只有12个,幂指数也只有大约40个

如果我们在计算器里做实验的话,阶乘本质上对于2进制来说,也只不过是每次能够多消去几个1罢了

那么一共有 1 < < 15 1<<15 1<<15种可能性,我们可以直接枚举所有的情况,然后剩下的1让2的幂次来枚举补充就可以了,每次统计答案最后在输出结果

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
ll n;
vector<ll> v;
int ans;

void solve(){
    ans = INF;
    cin >> n;
    for (ll i = 0; i < (1 << v.size()); i++){
        ll res = n;
        int cnt = 0;
        for (int j = 0; j < v.size(); j++){
            if((i >> j) & 1){
                res -= v[j];
                cnt++;
            }
        }

        if(res < 0)
            continue;

        for (int j = 0; j < 40; j++){
            if(((res >> j) & 1)){
                cnt++;
            }
        }

        ans = min(ans, cnt);
    }
    cout << ans << endl;
}

int main(){
    v.pb(1);
    ll x = 1;
    for (int i = 1; !(x > 1e12 || x < 0); i++){
        x *= i;
        if(x > 1e12 || x < 0)
            break;
        v.pb(x);
    }

    // cout << v.size() << Endl;

    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while(T--){
        solve();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值