SMU Autumn 2024 Personal Round 2
2024.9.22 12:00————15:20
过题数4/8
补题数5/8
- Not Adjacent Matrix
- Alyona and Numbers
- Pleasant Pairs
- Hossam and Friends
- Same Count One
- Shuffling Songs
- The Harmonization of XOR
- Division + LCP (hard version)
A - Not Adjacent Matrix
题解:
t组数据,每组数据给出一个数字n,要求输出一个n* n的数字矩阵,每个数字的上下左右的数字不能是与自己相差为1的数字,不重复得将数字1到n* n填充在矩阵中。
可以想象,如果将每个矩阵的右下角定为(n-1) * ( n-1)+1,从此开始的到n * n的数字交替分布在最右一列,最下一行。那么一定可以满足条件。注意当n等于2和n等于1的特殊情况。
也可以按奇偶分布。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[110][110];
void solve() {
int n;
cin >> n;
a[0][0] = 2;a[0][1] = 9;a[0][2] = 7;
a[1][0] = 4;a[1][1] = 6;a[1][2] = 3;
a[2][0] = 1;a[2][1] = 8;a[2][2] = 5;
for (int i = 3; i < 105; i++) {
int ls =i*i+1;
a[i][i] = ls++;
for (int j = 0; j < i; j++) {
a[i][j] = ls++;
a[j][i] = ls++;
}
}
if(n == 1) cout << 1 << endl;
else if(n == 2) cout << -1 << endl;
else {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << a[i][j] << ' ';
}cout << endl;
}
}
return ;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin >> t;
while(t--) {
solve();
}
return 0;
}
B - Alyona and Numbers
题解:
给出n和m,n代表有一个从1到n的数组,m代表有一个从1到m的数组,从其中任取俩个数字配成一对,问有多少对的和可以被5整除。
以数字较小的b为切入口,与b配对后的和的范围是b+1到b+a,遍历一遍b加上配对后的范围的满足条件数即可。
代码:
#include <iostream>
#include <set>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
using namespace std;
#define int long long
int x,y;
void solve() {
cin >> x >> y;
int a = x > y ? x : y;
int b = x > y ? y : x;
int ans = 0;
for (int i = 1; i <= b; i++) {
int mi = i;
int ma = i+a;
ans += (ma/5-mi/5);
// cout << ma << ' ' << mi << endl ;
// cout << ans << endl;
}cout << ans << endl;
return ;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin >> t;
while(t--) {
solve();
}
return 0;
}
C - Pleasant Pairs
题解:
t组数据,每组给出一个包含n个数字的数组a,满足数字不重复且小于n * 2,问其中有多少对(i,j)满足ai * aj=i+j,要求i<j。
遍历数组a,先固定a[i],开始寻找2 * a[i],3 * a[i]…,看看2,3…对应的位置是否满足要求,超出范围直接break。因为这样找出来相当于每个i都找到了属于自己的j,所以要➗2。
代码:
#include <iostream>
#include <set>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
#include<map>
using namespace std;
#define int long long
const int N = 1e5+10;
int ans = 0;
int n;
int a[N];
map<int,int>mp;
void solve() {
ans = 0;
cin >> n;
for (int i = 1; i <= 2*n; i++) mp[i] = -1;
for (int i = 1; i <= n; i++) {
cin >> a[i];
mp[a[i]] = i;
}
for (int i = 1; i <= n; i++) {
int res = a[i];
int aj = 1;
while(res <= i+n && aj <= 2*n) {
if(mp[aj] != -1) {
int wz = mp[aj];
if(res == i+wz && i != wz) {
// cout << i << ' ' << wz << endl;
ans++;
}
}
res += a[i];
aj++;
}
}cout << ans/2 << endl;
return ;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin >> t;
while(t--) {
solve();
}
return 0;
}
D - Hossam and Friends
题解:
t组数据,每组数据给出n个人,m对关系,m对关系里的x,y互相不喜欢,问在这n个人里,有多少组连续的人互相喜欢,自己也算一组。
数组a中储存每个人讨厌的人中离自己最近的。然后从最后一个往前遍历,如果后面那个人讨厌的人比自己讨厌的人离得更近,就把自己讨厌的最近的人定义成后面那个人讨厌的人,接着在这个区间内的所有组都是满足条件的。
代码:
#include <iostream>
#include <set>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
#include<map>
using namespace std;
#define int unsigned long long
#define endl "\n"
const int N = 1e6+10;
int n,m;
void solve() {
int a[N];
cin >> n >> m;
int ans = n;
for (int i = 1; i <= 100005; i++) a[i] = n+1;
for (int i = 0; i < m; i++) {
int x,y;
cin >> x >> y;
if(y > x) a[x] = min(a[x],y);
if(x > y) a[y] = min(a[y],x);
}
for (int i = n-1; i >= 1; i--) {
if(a[i] > a[i+1]) a[i] = a[i+1];
// cout << a[i] << ' ';
ans += (a[i]-i-1);
}
// for (int i = 1; i <= n; i++) {
if(a[i] == n+1) {
cout << n-i << ' ';
ans += n-i;
continue;
}
for (int j = a[i]-1; j >= i; j--) {
a[i] = min(a[i],a[j]);
a[j] = min(a[i],a[j]);
ans += (a[j]-j-1);
}
//if(a[i-1] > a[i]) {
//
//}
// for (int j = i; j < a[i]; j++) {
// a[i] = min(a[i],a[j]);
// }
// // cout << a[i]-i-1 << ' ';
// ans += (a[i]-i-1);
// }
cout << ans << endl;
return ;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin >> t;
while(t--) {
solve();
}
return 0;
}
E - Same Count One
题解:
t组数据,给定n行m列的数组a,a中只包含0,1俩个数字。可以在同一列中任意交换俩个数字,如果可以实现每行中的1的个数相等,输出操作,否则输出-1。
先遍历每一行,记录它是多了多少或者是少了多少,然后遍历每一列,有人多有人少,就记录一下,然后输出交换。并记得更改状态。
代码:
#include <iostream>
#include <set>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
#include<map>
using namespace std;
#define int long long
#define endl "\n"
const int N = 1e5+10;
string s[N];
int n,m;
int jia[N],ji[N];
int st[N];
void solve() {
memset(st,0,sizeof st);
cin >> n >> m;
int ii = 0,jj = 0;
int res = 0;
int ans = 0;
for (int i = 0; i < n; i++) {
string ss;
for (int j = 0; j < m; j++) {
int ls;
cin >> ls;
if(ls == 1) {
res++;
st[i]++;
}
ss += (ls+'0');
}
s[i] = ss;
}
if(res % n != 0) {
cout << -1 << endl;
return ;
}
int nm = res/n;
for (int i = 0; i < n; i++) {
// cout << st[i] << ' ';
if(st[i] > nm) {
ans += st[i]-nm;
}
}
cout << ans << endl;
for (int i = 0; i < m; i++) {
vector<int>a,b;
for (int j = 0; j < n; j++) {
if(s[j][i] == '1' && st[j] > nm) a.push_back(j);
if(s[j][i] == '0' && st[j] < nm) b.push_back(j);
}
// cout << a.size() << ' ' << b.size() << '/' << endl;
for (int j = 0; j < min(a.size(),b.size()); j++) {
cout << b[j]+1 << ' ' << a[j]+1 << ' ' << i+1 << endl;
st[a[j]]--;
st[b[j]]++;
}
}
return ;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin >> t;
while(t--) {
solve();
}
return 0;
}