Codeforces Round #828 (Div. 3) D-F

发布于:2022-10-17 ⋅ 阅读:(573) ⋅ 点赞:(0)

Problem - D - Codeforces

        (1)题目大意

                给定我们一个序列,你可以给每个ai*i,你最多给每个ai乘一个i,问最后是否能使这个序列的乘积能整除2^n。

         (2)解题思路

                很明显我们只需要2的因子个数达到n就行,我们首先遍历一遍原序列,然后看是否需要额外的2,如果需要我们需要从2的因子多的i开始进行贪心的拿,此时我们可以先预处理出来每个i2的因子的个数,如果把所有i拿完依旧不满足的话,那么则输出-1。

        (3)代码实现

#include "bits/stdc++.h"
using namespace std;
const int N = 2e5 + 10;
int num[N];
void init(int n)
{
    for(int i = 1;i <= n;i++) {
        int cnt = 0,p = i;
        while(p % 2 == 0) cnt ++,p /= 2;
        num[i] = cnt;
    }
}
void solve()
{
    int n,cnt = 0,x;
    cin >> n;
    vector <int> cost;
    for(int i = 1;i <= n;i++) {
        cin >> x;
        cost.push_back(num[i]);
        while(x % 2 == 0) cnt ++,x /= 2;
    }
    sort(cost.rbegin(),cost.rend());
    int op = 0;
    for(auto x:cost) {
        if(cnt < n) cnt += x,op ++;
        else break;
    } 
    if(cnt >= n) cout << op << endl;
    else cout << -1 << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    init(2e5);
    int T;
    cin >> T;
    while(T --) {
        solve();
    }
    return 0;
}

Problem - E2 - Codeforces        

        (1)题目大意

                给你四个数a,b,c,d,现在需要让求一个x和y,满足a<x<=c,b<y<=d,并且xy % ab==0。

        (2)解题思路

                因为我们x*y要整除a和b,那么x和y中肯定要包含a和b的因子,我们可以枚举每个a和b的因子,大概使log级别的组合,因此不会特别大,所以我们可以通过枚举a和b的因子,凑出x和y,若满足条件,则输出,否则枚举完所有的后,没有则输出-1 -1。

        (3)代码实现

#include "bits/stdc++.h"
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
void solve()
{
    ll a,b,c,d;
    cin >> a >> b >> c >> d;
    vector <ll> fac1,fac2;
    for(ll i = 1;i <= sqrtl(a);i++) {
        if(a % i == 0) {
            fac1.push_back(i);
            fac1.push_back(a / i);
        }
    }
    for(ll i = 1;i <= sqrtl(b);i++) {
        if(b % i == 0) {
            fac2.push_back(i);
            fac2.push_back(b / i);
        }
    }
    for(auto A:fac1)
        for(auto B:fac2) {
            ll v1 = A * B;
            ll v2 = a * b / A / B;
            ll x = a + 1,y = b + 1;
            if(x % v1) x += v1 - (x % v1);
            if(y % v2) y += v2 - (y % v2);
            if(x <= c && y <= d) {
                cout << x << ' ' << y << endl;
                return ;
            }
        }
    cout << -1 << ' ' << -1 << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T;
    cin >> T;
    while(T --) {
        solve();
    }
    return 0;
}

Problem - F - Codeforces

        (1)题目大意

        给定你一个序列,问你有多少个连续的子区间[l,r]满足mex([l,r]) > med([l,r])。mex指区间最小的为出现的非负整数,med是区间的中位数。

         (2)解题思路

                对于这个题,我们考虑固定其中一个,然后看跑的时候是否满足条件就行,对于固定中位数,显然是不太容易的,你得上数据结构。那么考虑固定mex,我们枚举每个mex,从1-n,对于每个mex,他顶多能二倍mex区间长度,因为大于这个区间长度的中位数至少大于等于这个mex。因此我们记录每个数的位置,从0的位置开始枚举。

                考虑四种情况

                1.若两倍长度已经小于当前枚举区间长度,显然答案已经被算过或者不存在,continue

                2.若当前这个数已经处于枚举的[l,r]中,那么显然答案已经被算过了,因此直接continue

                3.若当前这个数的位置在l左边,那么显然每移动一次都会让答案加上当前这个i+2*mex-1-R+1。(也就是固定当前这个i点,右边能给答案的贡献是可以o1算出来的)

                4.若当前之个数的位置在r右边,那么显然每移动一次都会让答案加上当前这个i-2*mex+1-l+1。(也就是固定当前这个i点,左边能给答案的贡献是可以o1算出来的)

      (3)代码实现

#include "bits/stdc++.h"
using namespace std;
const int N = 2e5 + 10;
int p[N],a[N];
void solve()
{
    int n;
    long long ans = 0;
    cin >> n;
    memset(p,0,sizeof(p));
    for(int i = 1;i <= n;i++) {
        cin >> a[i];
        p[a[i]] = i;
    }
    int l,r;
    l = r = p[0];
    for(int len = 1;len <= n;len ++) {
        if(len != n && p[len] >= l && p[len] <= r) continue;
        int dblen = 2 * len;
        if(dblen >= (r - l + 1)) {
            if(p[len] > r) {
                for(int i = r;i < p[len];i++) {
                    int j = max(1,i - dblen + 1);
                    ans += max(0,l - j + 1);
                }
            }
            else {
                for(int i = p[len] + 1;i <= l;i++) {
                    int j = min(n,i + dblen - 1);
                    ans += max(0,j - r + 1);
                }
            }
        }
        l = min(l,p[len]);r = max(r,p[len]);
    }
    cout << ans << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T;
    cin >> T;
    while(T --) {
        solve();
    }
    return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到