A、SSeeeeiinngg DDoouubbllee
一个字符串的每个字母翻倍,且没有其他限制。所以把字符串正着输一遍,再倒叙输出一遍即可。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 100010
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while (!isdigit(c)){
if(c == '-') s = -1;
c = getchar();
}
while(isdigit(c)){
x = x * 10 + (c ^ '0');
c = getchar();
}
a = x * s;
return ;
}
int main(){
int T; read(T);
while(T--){
string s;
cin >> s;
cout << s;
for(int i = s.length()-1; i >= 0; i--)
cout << s[i];
cout << endl;
}
return 0;
}
B、XOR = Average
对于奇数个的非常好想。全部输出 \(1\) 时可以发现刚好全部相等。
对于偶数个时,如下考虑:先将前 \(n - 2\) 个设为相同的某个数 \(x\),那么原式即为: \(a_1\) ^ \(a_2\) \(=\) \(\dfrac{(a_1 + a_2 + (n - 2) * x)}{n}\)。化简,可以变成:
\(n(a_1\) \(xor\) \(a_2) = a_1 + a_2 - 2x + nx\)。所以得到: \(a_1\) \(xor\) \(a_2 = x\) 且 \(a_1 + a_2 = 2x\)。枚举发现,\(a_1 = 1, a_2 = 3, x = 2\) 的时候成立。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 100010
int main(){
int T; cin >> T;
while(T--){
int n; cin >> n;
if(n % 2 == 1){
for(int i = 1; i <= n; i++) cout << 1 << " ";
}
else{
for(int i = 1; i <= n - 2; i++) cout << 2 << " ";
cout << "1 3";
}
cout << endl;
}
return 0;
}
C、Almost All Multiples
首先一个显然的结论,当且仅当 \(n\) 是 \(k\) 的倍数的时候,才存在这样的排列。反证:若将另外一个倍数放过来,则 \(n\) 也必定不能放在另外那个倍数的位置上。所以 \(n\) 不是 \(k\) 的倍数的时候,就不存在。
接着,先考虑一个通解:收尾按照要求放好,剩下的每个位置先放上自己,第 \(k\) 位则特殊地放 \(n\)。可以发现,对于 \(k\) 前面的位置,已经达到了字典序最优。所以考虑把 \(n\) 尝试往后移动。考虑 \(O(N)\) 做法:每次向后走,遇到一个数字,如果他恰好是 \(k\) 的倍数,而且 \(n\) 也是他的倍数,那么证明二者可以交换。值得注意的是,\(n\) 是所有数字中最大的,且我们优先变换较小的数字,所以这次操作对于字典序一定最优。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
int n, k;
int ans[N];
int main(){
int T; cin >> T;
while(T--){
cin >> n >> k;
if(n % k != 0) puts("-1");
else{
ans[1] = k;
ans[n]= 1;
for(int i = 2; i < n; i++){
if(i != k) ans[i] = i;
else ans[i] = n;
}
ans[n] = 1;
int now = k;
for(int i = k + 1; i < n; i++){
if(n % i == 0 && i % now == 0){
swap(ans[now], ans[i]);
now = i;
}
}
for(int i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}
}
return 0;
}
D、Range = √Sum
一道纯纯的构造题。对于 \(n\) 为偶数的情况,发现在以 \(n\) 为中心,半径为 \(/dfrac{n}{2}\) 的去心邻域内,所有整数组成的数列合法。
对于 \(n\) 为奇数的情况,如此考虑。先考虑以 \(n\) 为中心,半径为 \(/dfrac{n}{2}\) (向下取整) 的邻域中的所有连续整数,则有差值:\(n-1\)。和: \(n^2\)。
去掉根号,有:\(n^2 - 2n = 1\) 与 \(n^2\)。可以发现,最大与最小的值一个加一一个减一,和不变,但可以把差值变为 \(n^2 + 2n + 1\)。总体右移,总和增大 \(2n\),倒数第二个右移一位,总和加一。可以发现此时二者相等。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 100010
int main(){
int T; cin >> T;
while(T--){
int n; cin >> n;
if(n % 2 == 0){
for(int i = n / 2; i <= n * 3 / 2; i++){
if(i != n) cout << i << " ";
}
}
else{
vector <int> G;
for(int i = n - (n / 2); i <= n + (n / 2); i++)
G.push_back(i);
for(int i = 0; i < G.size(); i++)
G[i] += 2;
G[0] -= 1;
G[G.size()-1] += 1;
G[G.size()-2] += 1;
for(auto it : G){
cout << it << " ";
}
}
cout << endl;
}
return 0;
}