牛客暑期多校训练营7
发表于:2023-08-09 | 分类: 思维
字数统计: 938 | 阅读时长: 4分钟 | 阅读量:

更新至M,C…
这家呆不下去了,想去学校了

题M

题意:给定一个数字 nn,问从 11nnnn 个数中一共有多少单个数,如 1231231231,2,3 三个单个数字构成。

解:我们可以枚举一个数由几个单个数构成,当 n=1234n=1234 时, 可以将其拆解为 090-9109910-99100999100-999100012341000-1234,那么答案就是 1(90)+2(9910+1)+3(999100+1)+4(12341000+1)1*(9-0)+2*(99-10+1)+3*(999-100+1)+4*(1234-1000+1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int get(int x){
int k = 0; x /= 10;
while(x){
k = k * 10 + 9;
x /= 10;
}
return k;
}
int main(){
int n; cin >> n;
while(n --){
int x; cin >> x;
ll ans = 0;
for(int i = 1, j = 9; i <= 10; ++ i, j = j * 10 + 9){
int mx = min(j, x);
ans = ans + 1ll * (mx - get(mx)) * i;
if(mx == x) break;
}
cout << ans << '\n';
}
}

题C

题意:给定 n,kn,k,并且有长为 nn 的数组 AA 和长为 n1n-1 的数组 BB,其中 AiAi+1=BiA_i\oplus A_{i+1} =B_i,
同时对于数组 AA,满足 A_1\le A_2\le \dots\le A_n,0\le A_i,B_i \le 2\^{30},
对于满足的数组 AA, 求排列第 kk 小的数组 AA

解:由于 AiAi+1=BiA_i\oplus A_{i+1} =B_i,一个 A1A_1 即可得出所有 AiA_i, 我们求 BB 的前缀异或和 PrePre,那么我们就可以得到 Prei=A1Ai+1Pre_i=A_1\oplus A_{i+1}

Prei=A1Ai+1Pre_i=A_1\oplus A_{i+1}Ai+1=A1PreiA_{i+1} = A_1 \oplus Pre_i, 即 Ai=A1Prei1A_{i} = A_1 \oplus Pre_{i-1}
我们由 A1A2AnA_1\le A_2\le \dots\le A_n, 得 (A1Pre0)(A1Pre1)(A1Pren1)(A_1\oplus Pre_0) \le (A_1\oplus Pre_1)\le \dots\le (A_1 \oplus Pre_{n-1})
问题就转成了求第 kk 小的 A1A_1
于是,我们便可以枚举 A1A_1 的每个二进制位,假设 A1A_1 某个二进制位为 xx, 如果要满足上面不递减情况的话结果如下。

即当且仅当 PreiPre_iPrei+1Pre_{i+1} 的同一二进制位上两数一样,否则这个 A1A_1 的这个二进制位就是固定的。最终我们可以知道 A1A_1 有多少个不固定的二进制位,将其转化为十进制,在满足 k\ge k 的条件下,将二进制位补齐乃便是第 kk 小的 A1A_1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define pb(x) push_back(x)
#define PII pair<int, int>
#define INF 1ll << 30
#define ll long long
using namespace std;
const int N = 2e6 + 10, MOD = 1e9 + 7;
int b[N], a[35], pre[N];
void solve(){
ll n, k, num = 1 << 30, a1 = 0; cin >> n >> k;
for(int i = 1; i < n; ++ i) cin >> b[i]; pre[0] = 0;
for(int i = 1; i < n; ++ i) pre[i] = pre[i - 1] ^ b[i];
for(int i = 0; i <= 30; ++ i) a[i] = -1;
for(int i = 1; i < n; ++ i){
for(int j = 29; j >= 0; -- j){
int x = (pre[i - 1] >> j) & 1;
int y = (pre[i] >> j) & 1;
if(x + y == 1){
if(a[j] == -1) a[j] = x, num /= 2;
else if(a[j] != x){
cout << "-1\n";
return ;
}
break;
}
}
}
if(k > num) {cout << "-1\n"; return ;}
else k --;
for(int i = 0; k; k >>= 1){
while(a[i] != -1) i ++;
a[i] = k & 1;
}
for(int i = 0; i < 30; ++ i) if(a[i] == 1) a1 += (1 << i);
for(int i = 1; i <= n; ++ i){
a1 ^= b[i - 1];
cout << a1 << " \n"[i == n];
}
}
int main(){
//ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
while(n--) solve();
return 0;
}
上一篇:
牛客暑期多校训练营6
下一篇:
牛客暑期多校训练营5