这周主要是打蓝桥杯的训练赛,一场牛客一场cf,cf现在处于部分第四题赛后能出的阶段。
蓝桥杯1的题补的差不多了,感觉蓝桥杯的题都是能补的,争取在开学前补完。
题目链接:https://codeforces.com/contest/2064/problem/D
题意:给定一个数组 a , n个元素,q次询问,给一个x,x能和比他小的数 异或,x = x^a[i],
i 从 1-n,最多可以 异或 几次;
正解是状压dp,数据结构,想了一个3log的写法。
发现和比他小的数 y 异或,如果 y 的最高位和 x 一样,异或后一定会降位。如果最高位比 x 小,对答案没影响。不断二分找最高位和 x 一样的 y 就可以了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int a[200010];
int c[200010];
vector<int>v[10010];
void solve(){
int n,q;
cin >> n >> q;
for(int i = 1;i <= 30; ++i)v[i].clear();
for(int i = n;i >= 1; --i) cin >> a[i];
for(int i = 1;i <= n; ++i) c[i] = a[i]^c[i-1];
for(int i = 1;i <= n; ++i) {
int y = 0;
int x = a[i];
while( x ) {
y++;
x /= 2;
}
v[y].push_back(i);
}
while( q-- ) {
int x;
cin >> x;
int ans = 0;
for(int i = 1;i <= 30; ++i) {
int y = 0;
int xx = x^c[ans];
while( xx ) {
xx /= 2;
y++;
}
int d = n+1;
for(int j = 30;j > y; --j) {
auto tt = upper_bound(v[j].begin(),v[j].end(),ans);
if( tt != v[j].end() ) {
d = min(d,*tt);
}
}
auto t = upper_bound(v[y].begin(),v[y].end(),ans);
if( t == v[y].end() ) {
ans = d-1;
break;
}
if( *t >= d ) {
ans = d-1;
break;
}
d = *t;
ans = d-1;
if( (x^c[d-1]) >= a[d] ) ans = d;
else break;
}
cout << ans << " ";
}
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int T = 1;
cin >> T;
while( T-- ) solve();
return 0;
}
还有一题有意思的
一个lcm公式,化简为变成求 gcd(a[i],a[j],a[k]) 最小,原来lcm,gcd可以互相转换,都忘记了,让后用暴力枚举加枚举小技巧就可以写出来了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int a[200010];
void solve(){
int n;
cin >> n;
for(int i = 1;i <= n; ++i) {
int x;
cin >> x;
a[x]++;
}
int ansx = 0,ansy = 0,ansz = 0;
for(int i = 1;i <= 100000; ++i) {
int bj = 3;
int x = 0,y = 0,z = 0;
for(int j = i;j <= 100000; j += i) {
while( a[j] && bj ) {
if( bj == 3 )x = j,a[j]--,bj--;
else if( bj == 2 )y = j,a[j]--,bj--;
else z = j,a[j]--,bj--;
}
}
if( !bj ) {
ansx = x;
ansy = y;
ansz = z;
}
a[x]++;
a[y]++;
a[z]++;
}
cout << ansx << " " << ansy << " " << ansz;
}
signed main()
{
//ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int T = 1;
//cin >> T;
while( T-- ) solve();
return 0;
}