A. Sum of Round Numbers
(Description:)
给你一个数 (n),将其拆分为几个数的和,这几个数满足除最高位外,其余位全为 (0)。
(Solve:)
我直接以字符串读入,然后扫描一遍记下答案即可。
(Code:)
#include <bits/stdc++.h>
using namespace std;
int main(){
int t; cin >> t;
while(t --){
char num[10];
scanf("%s", num + 1);
vector<string> ans;
int len = strlen(num + 1);
for(int i = 1; i <= len; i ++){
if(num[i] == '0') continue; // 是 0 就跳过
string tmp = "";
tmp += num[i];
for(int j = 1; j <= len - i; j ++) tmp += '0'; // 加 0
ans.push_back(tmp);
}
cout << ans.size() << endl;
for(int i = 0; i < ans.size(); i ++) cout << ans[i] << " ";
puts("");
}
return 0;
}
(\)
B. Same Parity Summands
(Description:)
给你 (n, k) 两个数,问是否存在数组 (a) 满足 (n = a_1 + a_2 + a_3 +...+a_k) ?(a) 里的数要么都是奇数,要么都是偶数。
(Solve:)
根据 (n, k) 的奇偶性来分类讨论即可。
(Code:)
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N];
int main(){
int t; cin >> t;
while(t --){
int n, k; cin >> n >> k;
if(n & 1){
if(k & 1){
if(n < k) { puts("NO"); continue; } // 即使全为 1 都大于 n
for(int i = 1; i < k; i ++) a[i] = 1;
a[k] = n - k + 1;
}else{ // k 是偶数不合法
puts("NO"); continue;
}
}else{
if(k & 1){
if(n / 2 < k) { puts("NO"); continue; } // 是偶数每一项至少为 2
for(int i = 1; i < k; i ++) a[i] = 2;
a[k] = n - (k - 1) * 2;
}else{
// 这种情况下,每个数为奇数更优
if(n < k) { puts("NO"); continue; }
for(int i = 1; i < k; i ++) a[i] = 1;
a[k] = n - k + 1;
}
}
puts("YES");
for(int i = 1; i <= k; i ++) printf("%d ", a[i]);
puts("");
}
return 0;
}
(\)
C. K-th Not Divisible by n
(Description:)
给出 (n, k),输出不能被 (n) 整除的第 (k) 个数。
(Solve:)
对于每 (n) 个数,都有 (n - 1) 个数不能被 (n) 整除,那么根据这个我们可以轻易算出第 (k) 个数。
(Code:)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int t; cin >> t;
while(t --){
ll n, k; cin >> n >> k;
ll t = k / (n - 1);
ll c = k - t * (n - 1);
long long ans = t * n + (c > 0 ? c : -1); // c = 0 就必须 -1
cout << ans << endl;
}
return 0;
}
(\)
D. Alice, Bob and Candies
(Description:)
两个人轮流吃数组中的元素,一个从左往右,一个从右往左,第一次只吃 (a[i]),每次吃掉的元素和要严格大于上一个人吃的,求吃了几次和每个人吃了多少?
(Solve:)
直接按照题意模拟即可。
(Code:)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int arr[N];
int main(){
int t; cin >> t;
while(t --){
int n; cin >> n;
for(int i = 1; i <= n; i ++) scanf("%d", &arr[i]);
int l = 1, r = n, a = 0, b = 0;
int prev_a = 0, prev_b = 0; // 上次吃的总和
int i; // 移动次数
for(i = 1; ; i ++){
if(i & 1){
while(l <= r){
a += arr[l];
prev_a += arr[l ++];
if(prev_a > prev_b){
prev_b = 0;
break;
}
}
}else{
while(l <= r){
b += arr[r];
prev_b += arr[r --];
if(prev_b > prev_a){
prev_a = 0;
break;
}
}
}
if(l > r) break;
}
printf("%d %d %d
", i, a, b);
}
return 0;
}
(\)
E. Special Elements
(Description:)
长度为 (n) 的数组 (a),存在多少 (a_i = a_l + a_{l+1} + ... + a_r(1leq l < rleq n,a_i leq n)) ? 相同元素也要记入答案中。
(Solve:)
预处理出前缀和数组,然后来枚举区间 ([l, r]) ,记录答案即可。
(Code:)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4;
int a[N], sum[N], m[N];
int main(){
int t; cin >> t;
while(t --){
memset(m, 0, sizeof m);
int n; cin >> n;
sum[0] = 0;
for(int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
m[a[i]] ++; // 记录每个数出现的次数
sum[i] = sum[i - 1] + a[i]; // 前缀和
}
int ans = 0;
for(int l = 1; l <= n; l ++)
for(int r = l + 1; r <= n; r ++){
int t = sum[r] - sum[l - 1];
if(t > n) continue; // 每个数都是 <= n,> n 显然不合法
ans += m[t];
m[t] = 0; // 加了必须清空
}
cout << ans << endl;
}
return 0;
}
(\)
F. Binary String Reconstruction
(Description:)
对于一个二进制字符串 (s),给出 (n_0, n_1, n_2),分别代表在 (n - 1) 对相邻字符组里面全是 (0),有 (1) 有 (0),全是 (1) 的个数。输出满足一个这样条件的 (s)。
(Solve:)
显然 (len[s] = n_0 + n_1 + n_2 + 1)。直接暴力构造即可。左边为全 (0),中间为 (0, 1),右边为 (1) 即可。注意要判断一下 (n_1) 的奇偶性。
(Code:)
#include <bits/stdc++.h>
using namespace std;
int main(){
int t; cin >> t;
while(t --){
int n0, n1, n2; cin >> n0 >> n1 >> n2;
string s = "";
if(n1 == 0){ // 特判
for(int i = 1; i <= n0; i ++) s += '0';
for(int i = 1; i <= n2; i ++) s += '1';
s += n0 ? '0' : '1';
cout << s << endl;
continue;
}
for(int i = 1; i <= n0; i ++) s += '0';
if(n1 & 1){
for(int i = 1; i <= (n1 + 1) / 2; i ++){
s += '0'; s += '1';
}
}else{
for(int i = 1; i <= n1 / 2; i ++){
s += '0'; s += '1';
}
}
for(int i = 1; i <= n2; i ++) s += '1';
if((n1 & 1) == 0) {
s += '0';
}
cout << s << endl;
}
return 0;
}
(\)
G. Special Permutation
(Description:)
是否存在一种 ([1, n]) 的 排列使得相邻两个数差值的绝对值在 ([2, 4]) 之间?
(Solve:)
显然 (n < 4) 是无解的。
所以我的想法是在 (n = 4) 基础上推出其他的。
如果 (n) 是奇数,就加在上一项的后面;如果 (n) 是偶数,就在中间找一个可以插入的地方,是一定存在的。
理由,奇数显然是一定可以的,对于偶数的情况下,我们可以发现,对于 (n = 6) 的情况,是插入在 ((4, 2)) 之间的,那么就会存在 ((4, 6)),那么对于 (n = 8) 的情况就可以插入在 ((4, 6)) 之间,对于 (n = 10) 的情况就可以插入在 ((6, 8)) 之间,依次类推,对于 (n) (偶数)来说,可以插入在 ((n - 4, n - 2)) 之间,所以是一定有解的。
(Code:)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
vector<int> vec[N]; // vec[i] 代表 n = i 时的合法排列
// 预处理
void init(){
vec[4] = {3, 1, 4, 2};
for(int i = 5; i < N; i ++){
if(i & 1){ // 奇数直接加在上一项后面
vec[i] = vec[i - 1];
vec[i].push_back(i);
}else{
int mark = 0; // 标记是否加了 i
for(int j = 0; j < vec[i - 1].size(); j ++){
int num = vec[i - 1][j];
vec[i].push_back(num);
// 判断 vec[i - 1][j], i, vec[i - 1][j + 1] 这样是否合法,合法就插入
if(!mark && abs(i - num) >= 2 && abs(i - num) <= 4 && j < i - 2 && abs(i - vec[i-1][j+1]) >= 2 && abs(i - vec[i-1][j + 1]) <= 4){
vec[i].push_back(i);
mark = 1;
}
}
}
}
}
int main(){
init();
int t; cin >> t;
while(t --){
int n; cin >> n;
if(n <= 3) { puts("-1"); continue; }
for(int i = 0; i < n; i ++) cout << vec[n][i] << " ";
puts("");
}
return 0;
}