【CodeForces训练记录】Codeforces Round 1013 (Div. 3)

训练情况

赛后反思

A题题目读半天,发现日期有前导零,div3还是比较基础一点,但是感觉自己还是不够熟练,D题看出来二分但是调了挺久的

A题

判断取多少个数之后才能构成 20250301,我们维护数字的出现次数,直到所有数字的出现次数全部大于等于 20250301 的出现次数时输出位置即可

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

void solve(){
    string s = "20250301";
    vector<int> cnt1(10);
    vector<int> cnt2(10);
    for(int i = 0;i<s.size();i++) cnt1[s[i] - '0']++;
    int n; cin>>n;
    vector<int> a(n + 1);
    for(int i = 1;i<=n;i++) cin>>a[i];
    for(int i = 1;i<=n;i++){
        cnt2[a[i]]++;
        bool flag = true;
        for(int j = 0;j<=9;j++) if(cnt2[j] < cnt1[j]) flag = false;
        if(flag){
            cout<<i<<endl;
            return;
        }
    }
    cout<<0<<endl;
}

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

B题

题意是求 \(\min(a_i) \times len \ge x\) 的个数,首先我们发现对于 \(\ge x\) 的数,我们直接单独划分一组即可,单独一个数就能满足要求,接下来我们考虑 \(< x\) 的数,我们直接手玩能够发现优先考虑大的数一定比优先考虑小的数更优,例如

4 4
1 2 2 4

优先考虑小的数就需要 1 2 2 4 四个数,但优先考虑大的数可以划分 42 2

所以我们对数组从大到小排序,依次划分即可

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

void solve(){
    int n,x; cin>>n>>x;
    vector<int> a(n + 1);
    for(int i = 1;i<=n;i++) cin>>a[i];
    sort(a.begin() + 1,a.end(),greater<int>());
    int ans = 0;
    for(int i = 1;i<=n;i++){
        if(a[i]>=x){
            ans++;
            continue;
        }
        int r = i;
        while(r<n&&a[r]*(r-i+1)<x) r++;
        // cout<<i<<" "<<r<<endl;
        if(a[r]*(r-i+1)>=x) ans++;
        i = r;
    }
    cout<<ans<<endl;
}

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

C题

猜猜乐题,我们手玩发现对于奇数个的情况,我们构造一个数列从 \(n \sim 1\),一定存在中间一个元素相等,之后右移操作相当于每一位 \(+1 \mod n + 1\),所以每次移动都有一位能对上,偶数的情况我枚举了全排列发现都不行,直接盲猜无解

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

void solve(){
    int n; cin>>n;
    if(n&1){
        for(int i = n;i;i--) cout<<i<<" ";
        cout<<endl;
    } else {
        cout<<-1<<endl;
    }
}

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

D题

显然 \(k\) 个位置需要均摊到 \(n\) 行上,所以每行最多就有 \(\lceil \frac{k}{n} \rfloor\) 个座位,接下来我们只需要考虑一行想要让连续的座位尽可能小,显然一种构造方法就是连续几个空一格再连续几个,注意一下最后一段不需要空一格。所以我们考虑二分答案,通过连续的个数和列数计算出这一行最多能塞下多少个位置,再和之前每行最多的座位比较就是二分单调性了。

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

int n,m,k;
int lim;

bool pd(int x){
    int cnt = 0;
    cnt += m/(x+1)*x;
    cnt += m%(x+1);
    // cout<<x<<" "<<cnt<<endl;
    return cnt>=lim;
}

void solve(){
    cin>>n>>m>>k;
    lim = (k+n-1)/n;

    int l = 1,r = m,mid;
    while(l<r){
        mid = l + r >> 1;
        if(pd(mid)) r=mid;
        else l=mid+1;
    }
    cout<<l<<endl;
}

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

E题

我们显然知道 \(\operatorname{lcm}(a,b) = \frac{a \times b}{\gcd(a,b)}\)

所以题目中的函数 \(\frac{\operatorname{lcm}(x,y)}{{\gcd(x,y)}}\) 就变成了 \(\frac{a \times b}{\gcd^2(a,b)}\),我们考虑打表

对于 \(x=1\) 的情况,\(\gcd\) 一定等于 \(1\),所以 \(y\) 对答案的贡献当且仅当 \(y\) 为质数

对于 \(x=2\) 的情况,若 \(x,y\) 互质,显然 \(a \times b\) 出来一定不是质数,所以 \(b\) 一定是 \(a\) 的倍数,我们枚举倍数发现函数的值域为 \([2,\frac{y}{2}]\)

接下来问题就很简单了,求区间内质数个数,我们直接使用线性筛+前缀和统计个数即可,再 \(O(n)\) 跑一遍,计算 \([2,\frac{i}{2}]\) 的质数个数求和就是答案。

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

vector<int> cnt(1e7 + 3);

void pre(){
    int tot = 0;
    int n = 1e7;
    vector<bool> vis(1e7 + 3);
    vector<int> pri(1e7 + 3);
    for(int i = 2;i<=n;i++){
		if(!vis[i]){
            pri[++tot] = i;
			cnt[i]++;
		}
		for(int j = 1;i*pri[j]<=n&&j<=tot;j++){
			vis[i * pri[j]] = 1;
			if(i % pri[j] == 0) break;
		}
	}
    for(int i = 1;i<=1e7;i++) cnt[i] += cnt[i-1];
}

void solve(){
    int n; cin>>n;
    int ans = 0;
    for(int i = 1;i<=n;i++){
        ans += cnt[n/i];
    }
    cout<<ans<<endl;
}

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

posted @ 2025-03-26 00:50  MNNUACM_2024ZY  阅读(304)  评论(0)    收藏  举报