【CodeForces训练记录】Codeforces Round 1006 (Div. 3)
训练情况
赛后反思
结束前打表看出来了 F 有一点进制的规律,太极限了来不及写了
A题
显然不合法的情况就是所有元素绝对值的和都比和的绝对值小,这种情况无论怎么凑都到不了 \(k\),剩下的就是把和均摊到值域上,除以值域向上取整就是答案
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
using namespace std;
void solve(){
int n,k,p; cin>>n>>k>>p;
if(abs(n*p)<abs(k)) cout<<-1<<endl;
else cout<<abs(ceil(1.0*abs(k)/abs(p)))<<endl;
}
signed main(){
int T; cin>>T; while(T--)
solve();
return 0;
}
B题
简单的高中组合数学,我们显然发现 -_- 下划线放在中间,横杠放在两边,子序列个数为三部分的个数乘积,我们想要答案最大,根据均值不等式显然得对半分放在两侧,奇数偶数分类讨论即可
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
void solve(){
int n; cin>>n;
string s; cin>>s;
int cnt1 = 0,cnt2 = 0;
for(int i = 0;i<n;i++){
if(s[i] == '-') cnt1++;
else if(s[i] == '_') cnt2++;
}
if(cnt1&1){
int x = cnt1/2;
cout<<x*(x+1)*cnt2<<endl;
} else {
int x = cnt1/2;
cout<<x*x*cnt2<<endl;
}
}
signed main(){
int T; cin>>T; while(T--)
solve();
return 0;
}
C题
我们考虑从 0 开始到 n 枚举每一位是否可以放,因为按位或要等于 k,所以 k 的 0 位置不能出现 1,筛掉不合法的数,之后先将能放的数扔到答案数组里,如果不够 n 的话,直接补 x,按位或还是不变,如果超过 n 的话,会导致高位无法达到 x 的高位,按位或会不等于 x,这时候我们直接修改最后一位即可
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
void solve(){
vector<int> ans;
int n,x; cin>>n>>x;
vector<bool> vis(n + 1,1);
for(int i = 0;i<n;i++){
for(int j = 32;~j;j--){
if(((i>>j)&1)&& (((x>>j)&1) == 0)) vis[i] = 0;
}
}
for(int i = 0;i<n;i++){
if(vis[i]) ans.emplace_back(i);
}
while(ans.size() < n) ans.emplace_back(x);
int o = 0;
for(int i = 0;i<n;i++) o |= ans[i];
if(o!=x) ans[n-1] = x;
for(int i = 0;i<n;i++) cout<<ans[i]<<" ";
cout<<endl;
}
signed main(){
int T; cin>>T; while(T--)
solve();
return 0;
}
D题
显然区间左移我们可以等效看成最左边的数扔到区间最右边,对于操作区间 \([l,r]\),无论如何操作 l 左边的逆序对贡献不变,r 右边的逆序对贡献不变,贡献变的只是区间 \([l,r]\) 逆序对减少的个数,我们直接 \(O(n^2)\) 求大于当前位的数的个数和小于当前位的数的个数,贡献就是小-大,答案取大值更新 \(l,r\) 即可
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
using namespace std;
void solve(){
int n; cin>>n;
vector<int> a(n + 1);
vector<int> sm(n + 1),bi(n + 1);
for(int i = 1;i<=n;i++) cin>>a[i];
int now = 0;
int l = 1,r = 1;
for(int i = 1;i<=n;i++){
int cnt = 0;
for(int j = i+1;j<=n;j++){
if(a[j] < a[i]) sm[i]++;
else if(a[j] > a[i]) bi[i]++;
if(sm[i]-bi[i] > now){
now = sm[i] - bi[i];
l = i;
r = j;
}
}
}
cout<<l<<" "<<r<<endl;
}
signed main(){
int T; cin>>T; while(T--)
solve();
return 0;
}
E题
显然题目的公式可以推出来在直角三角形里 \(a+b=c,a^2+b^2=c^2\),代入后发现 \(ab = 0\),所以一定两人同在某一行或某一列答案才有贡献,因为求的是对数,我们考虑放在同一行,每增加一个人的贡献是一个首项 1,公差 1 的等差数列,题目人数又有限制,所以我们尽量放在一行让数列和尽可能接近 n,如果仍然不足跳到下一行,以此类推
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e9;
void solve(){
int n; cin>>n;
vector<pair<int,int>> ans;
int tot = 0,now = 0;
while(n){
++now;
int pos = 1;
int sum = 0;
while(sum+pos<=n){
sum += pos;
pos++;
}
for(int i = 1;i<=pos;i++) ans.push_back({now,i+tot});
tot += pos;
n-=sum;
}
cout<<ans.size()<<endl;
for(int i = 0;i<ans.size();i++){
cout<<ans[i].first<<" "<<ans[i].second<<endl;
}
}
signed main(){
int T; cin>>T; while(T--)
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具