https://codeforces.com/contest/1567
A
- 上面是左右排布的下面也一样,上面如果是上,下面就是下,反之上面是下,下面就是上
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int main(){
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int t, n;
string s;
cin >> t;
while(t--){
cin >> n;
cin >> s;
for(int i=0;i<n;i++){
if(s[i] == 'U') s[i] = 'D';
else if(s[i] == 'D') s[i] = 'U';
}
cout << s << '\n';
}
return 0;
}
B
给你一组自然数里面的最小不存在和异或和,问这组数最少有多少个
- 假设最小不存在是 a a a,异或是 b b b,那么至少应该有 [ 0 , a − 1 ] [0,a-1] [0,a−1]个数在里面,设异或和为 x x x,那么应该加入 x ⊕ b x\oplus b x⊕b,如果这个数是 a a a,那么需要调整,加入另外两个数让他们异或结果是 a a a,这可以做到;如果这个数不是 a a a,那么就加这个数即可
- 需要预处理异或和
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int a[MAXN];
int main(){
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
a[1] = 1;
for(int i=2;i<=300000;i++){
a[i] = (a[i - 1] ^ i);
}
int t;
cin >> t;
int l, r;
while(t--){
cin >> l >> r;
if(a[l - 1] == r){
cout << l << '\n';
continue;
}
else if((a[l - 1] ^ r) != l){
l += 1;
}else{
l += 2;
}
cout << l << '\n';
}
return 0;
}
C
给出了一种特殊的加法方式,如果需要进位,那么往左边隔一位上面进,现在给出两个数经过这种加法得到的结果,问这两个数有多少种情况
- 进位是在奇偶位置上分开进行的,故可以对奇偶位置分开来看,比如说如果和是 2021 2021 2021,那么分开看就是 1 1 1和 22 22 22, 1 1 1有几种组合情况呢?注意这里是正常的加法了,也就是 0 + 1 0+1 0+1和 1 + 0 1+0 1+0这样两种, 22 22 22有多少种组合方式呢?, 0 + 22 , 1 + 21 , 2 + 20 , . . . , 22 + 0 0+22,1+21,2+20,...,22+0 0+22,1+21,2+20,...,22+0,这显然是 23 23 23种情况,但是题目要求只能是正数,所以应该把 0 0 0去掉,组合起来一共有多少个存在某个数为 0 0 0的呢?只有 1 + 0 , 22 + 0 1+0,22+0 1+0,22+0和 0 + 1 , 0 + 22 0+1,0+22 0+1,0+22这样两种,所以答案应该是 ( a + 1 ) × ( b + 1 ) − 2 (a+1)\times(b+1)-2 (a+1)×(b+1)−2
- 上面所说的组合是这样进行的,比如说 0 + 1 0+1 0+1和 1 + 21 1+21 1+21如何组合呢?就是下面这个意思
- 所以容易理解这不会出现重复
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int main(){
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int t;
string s;
cin >> t;
while(t--){
cin >> s;
int a, b;
a = b = 0;
int len = s.length();
for(int i=0;i<len;i++){
if(i & 1){
a *= 10;
a += s[i] - '0';
}else{
b *= 10;
b += s[i] - '0';
}
}
cout << (a + 1) * (b + 1) - 2 << '\n';
}
return 0;
}
D
这题思路很简单,但是我愣是没写出来,感觉编码技术还是差得多…
- 输入 a , b a,b a,b,他问的是把 a a a拆成 b b b个数,然后这 b b b个数如果按照 11 11 11进制算和,问什么时候这个和最大,打印这 b b b个数的方案
- 这样考虑,就看 10 10 10这个数,如果让他变成 9 9 9,那么答案减少了 2 2 2,所以很明显分组的时候是高位剩下的越多越好,换句话说,能用 10 10 10绝不拆成 1 1 1,再换句话说,如果 10000 10000 10000要拆成若干个数,那肯定是先拆成 1000 , 1000... 1000,1000... 1000,1000...,然后再把 1000 1000 1000拆成 100 , 100... 100,100... 100,100...如果还不够,就把 100 100 100拆成 10 , 10... 10,10... 10,10...,再不够,就把 10 10 10拆成 1 , 1... 1,1... 1,1...
- 同时,高位之间是不影响的,也就是说拆成 1000 + 1000 + 1000 1000+1000+1000 1000+1000+1000和 2000 + 1000 2000+1000 2000+1000是一个效果
- 那么这个过程怎么实现呢?因为这个 b b b很小,可以很暴力,我们先从 i = 1 e 9 i=1e9 i=1e9开始筛选,将 a a a一点点的拆,如果当前这个数 a a a不到 i i i,那么就 i = i 10 i=\frac{i}{10} i=10i;否则是不是应该分了呢?,那就是分出来一个 i i i,这时候 b − 1 b-1 b−1,表示有一个数了,什么时候 b = 1 b=1 b=1,说明就剩下一个数,那这时候 a a a剩下多少就是多少;但这个时候需要考虑这个 i i i能不能分出来,比方说如果 100 100 100要分成 9 9 9个数,那不可能直接分出来个 100 100 100吧,这时候就要看分出来之后剩下的数还能不能分了,也就是比较一下 b − 1 b-1 b−1和 a − i a-i a−i之间的大小关系,如果 a − i ≥ b − 1 a-i\geq b-1 a−i≥b−1,说明还能分,哪怕是全分成 1 1 1,否则就不能分,这时候就往下走,也就是 i 10 \frac{i}{10} 10i
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
const int MAX = 1e9;
int main(){
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int t, s, n;
cin >> t;
while(t--){
cin >> s >> n;
vector<int> ans;
for(int i=MAX;i>=1;i/=10){
if(n == 1){
ans.push_back(s);
break;
}
if(s < i) continue;
if(s - i < n - 1) continue;
ans.push_back(i);
s -= i;
i *= 10;//这个位置技巧很好
n -= 1;
}
for(auto i : ans) cout << i << ' ';
cout << '\n';
}
return 0;
}
- 这道题考验的是编码技巧,就是暴力会不会写的问题,事实证明我不会写暴力…