题目链接
A. SSeeeeiinngg DDoouubbllee
题意:
给你一个字符串,这个字符串的double串就是这个字符串复制一遍,比如说abc的double串是aabbcc,现在让你重新排列这个double串,让其为回文串,输出这个回文串
思路:
直接他自己加上他的反串合并起来就行,下面看代码:
#include<bits/stdc++.h>
using namespace std;
void solve(){
string a;
cin>>a;
string b = a;
reverse(b.begin(),b.end());
cout<<a+b<<endl;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;
for(cin>>_;_;_--) solve();
return 0;
}
B. XOR = Average
题意:
给你一个n,让你构造出来一个数组,使得这个数组的异或和等于这个数组的平均数
思路:
如果是奇数的话直接全是1,偶数的话就1个2,1个6,剩下的都为4,下面看代码:
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin>>n;
if(n&1){
for(int i=1;i<=n;i++) cout<<1<<" ";
cout<<"\n";
}
else{
cout<<"2 6 ";
for(int i=1;i<=n-2;i++) cout<<4<<" ";
cout<<"\n";
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;
for(cin>>_;_;_--) solve();
return 0;
}
C. Almost All Multiples
题意:
给你一个n和一个x,让你构造一个长度为n的数组,是一个排列,且a[1] = x,a[n] = 1,并且构造的每个位置的数都能被其下标整除,输出字典序最小的序列,如果不能构造出来的话就输出-1
思路:
先看能不能构造出来,如果n是x的倍数,那么在下标为x的位置上填上n,其他的都不变就是一个序列,如果n不是x的倍数的话那么一定构造不出来,因为在x的位置上只能填x的倍数,那么x的倍数这个位置又空出来了,循环以往,就不行,那么如果n是x的倍数的话,还得有字典序最小这个条件,就是可能在x的位置不填n,填x的另一个倍数,然后后面的窟窿让n给填起来,这样做的字典序是最小的,直接枚举倍数就行,复杂度的话是调和级数,nlogn,下面看代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int mp[N],ans[N];
void solve(){
int n,x;
cin>>n>>x;
if(n%x == 0){
cout<<x<<" ";
for(int i=2;i<n;i++){
if(i==x){
bool flag = false;
for(int j=i+i;j<=n;j+=i){
if(n%j == 0){
flag = true;
cout<<j<<" ";
x = j;
break;
}
}
if(!flag) cout<<n<<" ";
}
else cout<<i<<" ";
}
cout<<1<<"\n";
}
else cout<<"-1\n";
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;
for(cin>>_;_;_--) solve();
return 0;
}
D. Range = √Sum
题意:
给你一个n,让你构造一个长度为n的数组,这个数组的数是两两不相同的,最大值减去最小值等于所有数的和的平方根
思路:
如果是偶数,就构造n-1,n+1,n-2,n+2,…,n-n/2,n+n/2,如果是奇数的话,就先n++,再扔一个n-1,因为这个时候的n-1是原来的n,保证和不变,然后其他的数都加一,这个时候也是满足题意的,下面看代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int mp[N],ans[N];
void solve(){
int n;
cin>>n;
if(n&1){
n++;
cout<<n+2<<" ";
for(int i=2;i<=n/2;i++){
cout<<n+i+1<<" "<<n-i+1<<" ";
}
cout<<"\n";
}
else{
for(int i=1;i<=n/2;i++){
cout<<n+i<<" "<<n-i<<" ";
}
cout<<"\n";
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;
for(cin>>_;_;_--) solve();
return 0;
}
E. Tick, Tock
题意:
每组样例给你一个n,m,d,其中n,m表示有n行m列的钟表,这个钟表是h进制的,取值范围是0~h-1,然后就是n*m的矩阵,a[i,j]代表第i行第j列的钟表的数字,如果是-1的话就代表这个表你可以任意选数,你可以进行一步操作将某一行或者是某一列的表都往前掰一下,问有多少种操作能使得这个矩阵中的数全变成相等的。
思路:
假如说有一种操作能把这个矩阵弄成全相等的,那么r[i]代表第i行操作的次数,c[j]代表第j列操作的次数,假设最后操作成的数是x,那么(a[i][j] + r[i] + c[j]) % h = x,这个式子是成立的,就是说r[i]一定是一个确定的数,在这种操作的情况下,不妨咱们把x设置成0,然后咱们枚举每一行或者是每一列,就是这一行或者是这一列什么也不操作,然后找他能影响到的行或者是列,相当于是一个并查集的操作,判断无解的情况就是并查集合并的时候发现他已经是别人的连通块里的了,而且那个数加上这个数也不等于当前的值,那么就直接返回0,否则就一直搜就行,下面看代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9+7;
int ksm(int x,int n){
int ans = 1;
while(n){
if(n&1) ans = ans * x % mod;
x = x * x % mod;
n >>= 1;
}
return ans;
}
void solve(){
int n,m,h;
int s = 0;
scanf("%lld%lld%lld",&n,&m,&h);
vector<int> r(n+1,-1),c(m+1,-1),st(n+m+1,0);
vector<vector<int> > a(n+1,c);
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%lld",&a[i][j]);
for(int i=1;i<=n+m;i++){
if(!st[i]){
s++;
st[i] = 1;
if(i<=n) r[i] = 0;
else c[i-n] = 0;
queue<int> q;
q.push(i);
while(!q.empty()){
int t = q.front();q.pop();
if(t <= n){
for(int j=1;j<=m;j++){
if(a[t][j] != -1){
if(!st[n+j]){
q.push(n+j);
st[n+j] = 1;
}
if(c[j] == -1) c[j] = ((a[t][j] - r[t]) % h + h) % h;
else{
if(a[t][j] != (c[j] + r[t]) % h){
printf("0\n");
return;
}
}
}
}
}
else{
t -= n;
for(int j=1;j<=n;j++){
if(a[j][t] != -1){
if(!st[j]){
q.push(j);
st[j] = 1;
}
if(r[j] == -1) r[j] = ((a[j][t] - c[t]) % h + h) % h;
else{
if(a[j][t] != (r[j] + c[t]) % h){
printf("0\n");
return;
}
}
}
}
}
}
}
}
printf("%lld\n",ksm(h,s-1));
}
signed main(){
int _;
for(cin>>_;_;_--) solve();
return 0;
}