Codeforces Round #851 (Div. 2) (A、B、C)

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题

Problem - C - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1788/problem/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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dawpro_加薪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值