CF 试题泛做 *1600-2000
https://codeforces.com/problemset?tags=1600-2000
https://codeforces.com/contest/1632/problem/C
题意:对于或操作我们有
对于 组数据,给两个数 你可以执行任意次的以下的三个操作。
问最少多少次的操作,可以使得 。
分析:
我们有 。
因此第三个操作会使得 ,如果等于就结束了,如果大于的话,接下来一直执行操作 才能使得 接近于 。因此最多执行一次第三个操作。
如果不执行,那么花费 的代价。
如果执行,那么执行之后 只会因为某一位 的时候出现。我们可以选择在执行之前对 或者 进行 操作,或者在执行之后对 进行操作,从而满足要求。
如果是执行之后操作(目的是 ),那么和执行之前操作 的位数是一样的。并且在 的情况下,如果后操作会节省一些额外的 步骤。
因此只有两种可能:增加 然后取或,增加 然后取或。(取或的临界条件是取或之后就可以相等)
分别枚举计算即可。时间复杂度 。
如果我们进行优化,直接算出增加的次数,那么时间复杂度可以优化到 :按位模拟,向前进位,累加贡献,直到没有这样的位数为止。
#include<bits/stdc++.h>
using namespace std;
#define f(i, a, b) for(int i = a; i <= b; i++)
#define mod9 998244353
#define mod1 1000000007
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define endl '\n'
int t;
int main(){
ios::sync_with_stdio(0);
cin.tie(NULL);
cout.tie(NULL);
cin >> t;
while(t--) {
int a, b; cin >> a >> b;
int ans = b - a;
for(int x = a; ; x++) {
if(( x | b ) == b) {
ans = min(ans, x - a + 1);
break;
}
}
for(int x = b; ; x++) {
if(( x | a ) == x) {
ans = min(ans, x - b + 1);
break;
}
}
cout << ans << endl;
}
return 0;
}
https://codeforces.com/contest/1658/problem/D1
题意:给定 ,一开始有一个 的排列,每个数异或 后变成了 数组。给定 数组,求一个可行的 。
分析:对于每一位,若 的这一位是 ,那么原排列每一个这一位都取反,否则不变。对于原数组(我们知道它是 )和 ,每一位分别计数看看有没有发生取反即可确定 的这一位是什么。
#include<bits/stdc++.h>
using namespace std;
#define f(i, a, b) for(int i = a; i <= b; i++)
#define mod9 998244353
#define mod1 1000000007
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define endl '\n'
int a[200010];
bool xbit[20]; //每一位是什么
int x = 0;
int main(){
ios::sync_with_stdio(0);
cin.tie(NULL);
cout.tie(NULL);
int t; cin >> t;
while(t--) {
int l, r; cin >> l >> r;
f(i,l, r) cin>>a[i];
int cnta = 0, cntn = 0;
for(int i = 0; i <= 17; i++) {
for(int j = 0; j <= r; j++) {
if((a[j] >> i) & 1) cnta++;
if((j >> i) & 1) cntn++;
}
if(cnta == cntn) xbit[i] = 0;
else xbit[i] = 1;
cnta = cntn = 0;
x += (xbit[i] << i);
}
cout << x << endl;
x = 0;
}
return 0;
}
( 的时候,为什么这个做法假了呢?)
问题主要是在 的时候。
某一位上如果 的个数和 的个数相等,那么不管是异或 还是 都不会改变个数。但有的时候我们不总是可以任选一个。
例如以下例子:
但为什么 的时候可以?因为如果这一位上是偶数,那么其前面的内容一定是成对出来的,如果整体异或 只是调换了位置,不会改变个数。
例如以下例子:
(形式化地:若 在 内,那么 也一定在。)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】