【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 四个数,但优先考虑大的数可以划分 4、2 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;
}

浙公网安备 33010602011771号