A题:
思路:没有负数时选择最大的正数,有负数则选负数。
代码:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 3e5 + 10;
typedef long long ll;
typedef pair<int, int> PII;
void solve()
{
int n, x;
cin >> n;
vector<int> p, ne;
for (int i = 0; i < n; i++)
{
cin >> x;
if (x >= 0)
p.push_back(x);
else
ne.push_back(x);
}
sort(p.begin(), p.end());
if (ne.size() == 0)
cout << p.back() << endl;
else
cout << ne.back() << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(0);
int t;
// t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
B题
思路:交换最大的数使得1和2之间有最大的数,当我们发现1和2之间有最大的数的时候我们无论这么删除都得不到一个子数组,这样我们的子数组的个数就是2,也就是最少的。
代码实现:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 3e5 + 10;
typedef long long ll;
typedef pair<int, int> PII;
void solve()
{
int n, pos1, pos2, maxx;
cin >> n;
vector<int> a;
for (int i = 0, x; i < n; i++)
{
cin >> x;
a.push_back(x);
if (x == 1)
pos1 = i + 1;
if (x == 2)
pos2 = i + 1;
if (x == n)
maxx = i + 1;
}
bool flag = 0;
for (int i = min(pos1, pos2); i <= max(pos1, pos2); i++)
if (a[i - 1] == n)
flag = 1;
if (flag == 0)
{
if (pos1 < pos2)
{
if (maxx > pos2)
cout << pos2 << " " << maxx << endl;
else
cout << pos1 << " " << maxx << endl;
}
else
{
if (maxx > pos1)
cout << pos1 << " " << maxx << endl;
else
cout << pos2 << " " << maxx << endl;
}
}
else
cout << "1 1" << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
C题
思路:
赛时的麻烦想法:
当我们行数和列数都是合数的时候,我们直接正常的按顺序放数字即可,当我们的行列有一个是素数一个是合数的时候,我们会知道以合数为列我们不需要改变顺序,当列数是合数的时候我们先按照列行排一个顺序,饭后反转即可得到正确的顺序,最后对于行列都是素数的情况下我们需要一些特殊的方法处理,比如7行我们可以对调1和4行,3和6行,这样一换,我们2行的上下都是差列数的若干倍,即一个合数,这样我们就会满足题目要求。(1,4) (3,6) (5 ,8)这样的行数正好也有规律,我们就先预处理出来我们的行数顺序,然后输出的时候按照正确的顺序输出即可。
代码:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 1010;
typedef long long ll;
typedef pair<int, int> PII;
int ans[N][N];
int h[N][N];
bool is_prime(int x)
{
if (x < 2)
return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0)
return false;
return true;
}
void init()
{
for (int i = 1; i <= 1000; i++)
for (int j = 1; j <= 1000; j++)
{
h[i][j] = j;
}
swap(h[5][1], h[5][4]);
swap(h[5][3], h[5][5]);
for (int i = 6; i <= 1000; i++)
{
if (is_prime(i))
{
for (int j = 1; j <= i; j += 2)
{
if (j + 3 <= i)
swap(h[i][j], h[i][j + 3]);
}
}
}
}
void solve()
{
int n, m, cnt = 1;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
ans[i][j] = cnt++;
if ((!is_prime(n) && !is_prime(m)) || (is_prime(n) && !is_prime(m)))
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
cout << ans[i][j] << " ";
cout << endl;
}
}
else if (!is_prime(n) && is_prime(m))
{
int cnt = 1;
for (int j = 1; j <= n; j++)
{
for (int i = 1; i <= m; i++)
cout << j + n * (i - 1) << " ";
cout << endl;
}
}
else
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
cout << ans[h[n][i]][j] << " ";
cout << endl;
}
}
}
int main()
{
// iostream::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
init();
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
后来和朋友交流得到:我们直接对所有的第一列的行号都处理一下,使得相邻的两行之间都差列数的若干倍,这样以来我们就没必要分前面的几种情况来讨论了(毕竟合数的倍数还是合数,素数的倍数是合数)。
代码:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 1010;
typedef long long ll;
typedef pair<int, int> PII;
int ans[N][N];
void solve()
{
int n, m, cnt = 1;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
ans[i][j] = cnt++;
deque<int> q;
q.push_back(1);
cnt = 1;
for (int i = n; i >= 2; i--)
{
if (cnt % 2 == 1)
q.push_front(i);
else
q.push_back(i);
cnt++;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cout << ans[q[i - 1]][j] << " \n"[j == m];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}