Problem A SSeeeeiinngg DDoouubbllee
double长度输入字符串,并输出double后该字符串的任意回文字符串
思路:建立一个长度2n的数组,依次读入输入字符,每读到一个字符,将首尾各添加一个这样的字符,读完后输出即可。
或者直接输出输入字符串,再使用反向iterator,构建该字符串的逆序字符串,再输出即可。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int N;
cin >> N;
while (N--){
string s;
cin >> s;
cout << s << string(s.rbegin(), s.rend()) << endl;
}
}
思路:题目要求将n个数进行XOR运算,并且运算后的结果等于这N个数的平均值。XOR的特性:a与a自己XOR运算是0。bit位与1运算是取反操作。 根据这个特性,可以构造平均值为1的序列,因为1与1XOR运算结果是0,只要保证输入n是奇数即可。对于输入是偶数的序列,可以提取n-2个2做XOR运算,运算结果是0,然后剩下的两个数取1和3,可以保证平均值跟XOR值为2。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int N;
cin >> N;
while(N--){
int n;
cin >> n;
if (n %2 != 0){
for (int i = 0; i < n; ++i){cout << 1 << "\n "[i < n - 1];}
}
else{
for (int i = 0; i < n - 2; ++i){cout << 2 << " ";}
cout << 1 << ' ' << 3 << endl;
}
}
}
Problem C Almost All Multiples
题意:给2个数字n和x,n代表数组长度,并且将x放在该数组的第一位,1放在该数组的最后一位。问:能不能找出一个数组,这个数组的a[i] % i == 0(i∈[1, n]),并且这个数组是permutation数组(permutation数组是指这个数组排序后是从1开始每次递增1的序列)。如果能,则输出这个数组,否则输出-1。
思路:题目要求x值放在第一位,1放在最后一位。这也意味着x把1的位置占掉了,1把n的位置占掉了。所以对于我们要找的permutation序列,只要判断n是否能放在x的位置,即n%x的数组下标==0,如果可以,那么首位输出x,末位输出1,x位输出n,其他下标输出下标*1即可(这里的前提是下标∈[1,n],如果采用[0, n-1]存储方式在访问时将指针加1即可。如果n%x != 0,输出-1。
但是第一次跑代码没跑过去,发现题目还有一个要求,即输出字典序最小的数(意思就是大数靠后排,比如在数组下标3,6和12 mod 3的结果都是0,但是要把6放在下标3,12放在下标6)。所以考虑到可能是n代替x以后,出现了比n更小的数,可以放在x的位置,所以需要将n的位置更新一下。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int N;
cin >> N;
while(N--){
int n, x;
cin >> n >> x;
if (n % x == 0){
vi a(n + 1);
for (int i = 2; i < n; ++i){a[i] = i;}
a[1] = x; a[x] = n;a[n] = 1; //a[n] = 1要放在上一个语句后面,避免了n==x的情况
//下面开始更新n的位置,如果n % x*i == 0 并且 x*i % cur_pos == 0说明x * i 可以放在cur_pos的位置,cur_pos表示n现在的位置
int cur_pos = x;
for (int i = 1; i * x < n; ++i){
if (n % (x * i) == 0 && (x * i) % cur_pos == 0){swap(a[cur_pos], a[x * i]); cur_pos = x * i;}
}
for (int i = 1; i < n + 1; ++i){cout << a[i] << " \n"[i == n];}
}
else{cout << "-1\n";}
}
}
Problem D. Range = √Sum
题目大意:给一个输入n代表要构建的数组长度,根据这个长度构建所有的元素都distinct的元素,且最大元素与最小元素的值 == sqrt(sum(构建的数组))。
思路:这种构造题型,要找规律。根据输入n构建n个数,而且求和的均值和最大最小值都等于这个数。那么尝试着构造均值为n的数组。以输入6为例:均值为6的数组构建为[3, 4, 5, 7, 8,9],均值与最大最小差值均为6。所以对于输入是偶数的情况可以以n分分界线,输出n左边的n/2个数与右边的n/2个数。针对奇数情况,要去掉一个数,并且sum不变,那么可以去掉任意一个小于n的数,将n分配到数组中的其他数上即可。针对n = 5,先写出[3, 4, 5, 7, 8, 9]再将3加到最右边的三个数得到[4, 5, 8, 9, 10]满足题意。或者将4加到最大最小元素上,剩下两个值随意加,得到[4, 6, 7, 9, 10]。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int N;
cin >> N;
while(N--){
int n;
cin >> n;
if (n % 2 == 0){
for (int i = n / 2; i < n; ++i){cout << i << ' ';}
for (int i = n + 1; i < n + n / 2 + 1; ++i){cout << i << " \n"[i == n + n / 2];}
}
else{
n += 1;
for (int i = n / 2 + 1; i < n; ++i){cout << i << ' ';}
for (int i = n + 2; i < n + n / 2 + 2; ++i){cout << i << " \n"[i== n + n / 2 + 1];}
}
}
}