A题
Problem - A - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1788/problem/A题意:
本题是给定一个只包含数字1和2的数组,找到一个位置k,其中 1 <= k <= n - 1,使得数组1-k和k + 1 到 n 的乘积相等。
思路:
直接遍历数组,记录2的数目num即可,如果num 是个奇数,那么肯定不可能找到满足条件的位置k,反之,我们直接遍历数组,新开一个数x记录2的数目,每遇到一个2的时候就x++,当x等于num的一半的时候就找到了k。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1010;
int T, n;
int a[N];
signed main()
{
cin >> T;
while(T--)
{
scanf("%d", &n);
int sum = 0;
for (int i = 1; i <= n; ++ i)
{
scanf("%d", &a[i]);
if(a[i] == 2) sum ++;
}
if(sum % 2 != 0) puts("-1");
else {
int k = 0;
for (int i = 1; i <= n; ++ i)
{
if(a[i] == 2) ++ k;
if(k == sum / 2)
{
printf("%d\n", i);
break;
}
}
}
}
return 0;
}
B题
Problem - B - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1788/problem/B题意:
本题题意是给定一个数n,让我们找到两个数x和y,使得x + y = n的同时,x和y的数位之和相差不超过1。
思路:
简而言之就是取中值,然后对于极端情况进行讨论。
我们可以从例子中观察出,除了19,199,1899.....这类型的数,其他的数都可以通过取中值,然后如果n是奇数,就输出mid 和 mid + 1, 否则就输出两个mid即可。
极端情况讨论:
对于数据尾端有直通末尾的9的时候,例如199,我们进行取中之后并不能得到满足题意的答案,因为此时mid + 1 末尾一定会由9变为0,那么我们需要考虑一下如何进行特殊情况的讨论。首先我们看到末尾如果有1个9,如19,那么满足题意的数可以是14和5,那么如果有2位呢,如199,我们进行实际操作,发现mid = 99,而mid + 1 = 100,现在相当于末尾有两个9,那么我们是不是可以直接分摊就行,变成109和 90,我们可以看到一下子就满足了,那么往宽泛扩展,我们是不是有理由相信,直通末尾的9(如1908中的9就不属于直通末尾)每两个都可以均摊,而均摊到最后最多只剩下一个9,我们直接用4和5分配即可,因为mid + 1肯定有一位是大于mid的(因为有连通末尾的9肯定+1会进1)那么我们将4分给mid + 1,将5分给mid即可。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int T;
vector<int> a, b;
void ins_a(int u)
{
while(u > 0)
{
a.push_back(u % 10);
u /= 10;
}
}
void ins_b(int u)
{
while(u > 0)
{
b.push_back(u % 10);
u /= 10;
}
}
int did(int x)
{
int ans = 0;
while(x > 0)
{
if(x % 10 == 9) ans ++, x /= 10;
else break;
}
return ans;
}
signed main()
{
scanf("%d", &T);
int n;
while(T--)
{
a.clear();
b.clear();
scanf("%d", &n);
int mid = n / 2;
if(n % 2 == 0) printf("%d %d\n", mid, mid);
else {
int num = did(mid), po = 0;
if(num == 0) printf("%d %d\n", mid, mid + 1);
else {
ins_a(mid), ins_b(mid + 1);
while(num > 0)
{
if(num == 1) a[po] = 5, b[po] = 4;
else {
a[po + 1] = 0, b[po + 1] = 9;
po += 2;
}
num -= 2;
}
bool fis = true;
for (int i = a.size() - 1; i >= 0; -- i)
{
if(fis && a[i] == 0) continue;
if(a[i] != 0) fis = false;
printf("%d", a[i]);
}
cout << ' ';
for (int i = b.size() - 1; i >= 0; -- i) printf("%d", b[i]);
puts("");
}
}
}
return 0;
}
C题
本题是给你一个数n,让你从1 - 2n(每个数有且仅有1次配对机会)中不断配对使得最终每一对的和是一个 d 为1的等差数列。
思路:
本题只要多往后写两个样例,比如5和6,就一下能看出来规律了,首先我们可以观察出可以找到结果的条件是n - 1是偶数,如果不满足,直接输出“No”即可,反之,我们可以观察到,配对其实是有严格规律的,那就是从 1 - 2n ,去掉1 和 2n之后,剩余数平分,左边分为偶数(2起)和奇数(3起),右边继续平分,分为右左和右右,那么我们就直接将左边偶数(从小到大)与右左(从大到小)配对,左边奇数(从小到大)与右右(从大到小)配对即可。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int T;
signed main()
{
scanf("%d", &T);
int n;
while(T--)
{
scanf("%d", &n);
if((n - 1) % 2 != 0) puts("No");
else {
puts("Yes");
printf("%d %d\n", 1, n * 2);
int l = 3, r = n * 2 - 1, fl = 2, fr = r - ((n - 1) / 2), ci = n - 1;
int x = ci / 2, y = ci / 2;
while(x --)
{
int ansl = fl, ansr = fr;
fl += 2, fr --;
printf("%d %d\n", ansl, ansr);
}
while(y --)
{
int ansl = l, ansr = r;
l += 2, r --;
printf("%d %d\n", ansl, ansr);
}
}
}
return 0;
}