CodeForces 625D Finals in arithmetic

神奇的构造题,我的思路比较奇葩。搞了好久,看到WA on 91我绝望了,然后自己造数据,找到了错误,总算是AC了,现在是凌晨0:24分,看到AC之后,感动China!

我写的代码无比的长。。。。。应该有很简单的方法吧。。。。。没想到。

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <stack>
#include <map>
#include <vector>
using namespace std;

const int maxn = 100000 + 100;
char s[maxn];
int a[maxn], b[maxn], sum[maxn], flag[maxn];
int tmpa[maxn], tmpb[maxn], ans[maxn];
int nb[maxn];
int len;


void read()
{
    scanf("%s", s);
    for (int i = 0; s[i]; i++) b[i + 1] = s[i] - '0';
    nb[1] = b[1] * 10 + b[2]; for (int i = 2; s[i]; i++) nb[i] = s[i] - '0';
}

void init()
{
    len = strlen(s);
    memset(flag, 0, sizeof flag);
}

bool check1()
{
    for (int i = 1; i <= (len + 1) / 2; i++)
    {
        if (sum[i] % 2 == 0) a[i] = sum[i] / 2, a[len - i + 1] = sum[i] / 2;
        else a[i] = sum[i] / 2 + 1, a[len - i + 1] = sum[i] - a[i];
    }

    for (int i = 1; i <= len; i++) tmpa[i] = a[i];
    for (int i = 1; i <= len; i++) tmpb[i] = a[len - i + 1];

    int k = 0;
    for (int i = 1; i <= len; i++)
    {
        ans[i] = (tmpa[i] + tmpb[i] + k) % 10;
        k = (tmpa[i] + tmpb[i] + k) / 10;
    }

    for (int i = 1; i <= len; i++)
    if (b[len - i + 1] != ans[i]) return 0;
    return 1;
}

bool work1()
{
    bool fail = 0; init();

    for (int i = len; i >= len / 2 + 1; i--)
    {
        int id_now = i, id_pre = len - i + 1;

        if (i == len)
        {
            if (b[i] == 0) { fail = 1; break; }

            sum[id_now] = b[id_now]; sum[id_pre] = b[id_now];
            flag[id_now] = 0; flag[id_pre] = 0;

            if (b[id_now] == b[id_pre]) flag[id_pre + 1] = 0;
            else if (b[id_now] + 1 == b[id_pre]) flag[id_pre + 1] = 1;
            else { fail = 1; break; }
        }

        else
        {
            int num_now, num_pre;
            num_now = b[id_now] - flag[id_now + 1];

            if (num_now == 9)
            {
                if (b[id_pre] == 9)
                {
                    sum[id_now] = 9; sum[id_pre] = 9;
                    flag[id_pre + 1] = 0;
                }
                else if (b[id_pre] == 0)
                {
                    sum[id_now] = 9; sum[id_pre] = 9;
                    flag[id_pre + 1] = 1;
                }
                else { fail = 1; break; }
            }
            else if (b[id_now] == 0 && flag[id_now + 1])
            {
                if (b[id_pre] == 9 || b[id_pre] == 0)
                {
                    flag[id_now] = 1;
                    if (b[id_pre] == 0) flag[id_pre + 1] = 1;
                    sum[id_now] = 9;
                    sum[id_pre] = 9;
                }
                else { fail = 1; break; }
            }
            else
            {
                num_now = num_now + flag[id_pre] * 10;
                num_pre = b[id_pre] + flag[id_pre] * 10;

                if (num_now == num_pre)
                {
                    flag[id_pre + 1] = 0;
                    sum[id_now] = num_now; sum[id_pre] = num_now;
                    if (num_now >= 10) flag[id_now] = 1;
                }

                else if (num_now + 1 == num_pre)
                {
                    flag[id_pre + 1] = 1;
                    sum[id_now] = num_now; sum[id_pre] = num_now;
                    if (num_now >= 10) flag[id_now] = 1;
                }
                else { fail = 1; break; }
            }
        }
        if (id_now == id_pre&&sum[id_pre] % 2 != 0) { fail = 1; break; }
    }

    if (!check1()) fail = 1;

    return fail;
}

bool check2()
{
    memset(tmpa, 0, sizeof tmpa);
    memset(tmpb, 0, sizeof tmpb);

    for (int i = 1; i <= (len + 1) / 2; i++)
    {
        if (sum[i] % 2 == 0) a[i] = sum[i] / 2, a[len - i + 1] = sum[i] / 2;
        else a[i] = sum[i] / 2 + 1, a[len - i + 1] = sum[i] - a[i];
    }

    for (int i = 1; i <= len; i++) tmpa[i] = a[i];
    for (int i = 1; i <= len; i++) tmpb[i] = a[len - i + 1];

    int k = 0;
    len++;
    for (int i = 1; i <= len; i++)
    {
        ans[i] = (tmpa[i] + tmpb[i] + k) % 10;
        k = (tmpa[i] + tmpb[i] + k) / 10;
    }

    for (int i = 1; i <= len; i++)
    if (b[len - i + 1] != ans[i]) return 0;
    return 1;
}

bool work2()
{
    bool fail = 0; init();

    len--;

    for (int i = len; i >= len / 2 + 1; i--)
    {
        int id_now = i, id_pre = len - i + 1;

        if (i == len)
        {
            sum[id_now] = 10 + nb[id_now]; sum[id_pre] = 10 + nb[id_now];
            flag[id_now] = 1; flag[id_pre] = 1;

            if (nb[id_now] + 10 == nb[id_pre]) flag[id_pre + 1] = 0;
            else if (nb[id_now] + 10 + 1 == nb[id_pre]) flag[id_pre + 1] = 1;
            else { fail = 1; break; }
        }

        else
        {
            int num_now, num_pre;
            num_now = nb[id_now] - flag[id_now + 1];

            if (num_now == 9)
            {
                if (nb[id_pre] == 9)
                {
                    sum[id_now] = 9; sum[id_pre] = 9;
                    flag[id_pre + 1] = 0;
                }
                else if (nb[id_pre] == 0)
                {
                    sum[id_now] = 9; sum[id_pre] = 9;
                    flag[id_pre + 1] = 1;
                }
                else { fail = 1; break; }
            }
            else if (nb[id_now] == 0 && flag[id_now + 1])
            {
                if (nb[id_pre] == 9 || nb[id_pre] == 0)
                {
                    flag[id_now] = 1;
                    if (nb[id_pre] == 0) flag[id_pre + 1] = 1;
                    sum[id_now] = 9;
                    sum[id_pre] = 9;
                }
                else { fail = 1; break; }
            }
            else
            {
                num_now = num_now + flag[id_pre] * 10;
                num_pre = nb[id_pre] + flag[id_pre] * 10;

                if (num_now == num_pre)
                {
                    flag[id_pre + 1] = 0;
                    sum[id_now] = num_now; sum[id_pre] = num_now;
                    if (num_now >= 10) flag[id_now] = 1;
                }

                else if (num_now + 1 == num_pre)
                {
                    flag[id_pre + 1] = 1;
                    sum[id_now] = num_now; sum[id_pre] = num_now;
                    if (num_now >= 10) flag[id_now] = 1;
                }
                else { fail = 1; break; }
            }
        }
        if (id_now == id_pre&&sum[id_pre] % 2 != 0) { fail = 1; break; }
    }

    if (!check2()) fail = 1;

    return fail;
}


int main()
{
    read();
    init();
    if (!work1())
    {
        for (int i = 1; i <= len; i++) printf("%d", a[i]);
        printf("\n");
    }
    else
    {
        if (b[1] == 1)
        {
            if (!work2())
            {
                for (int i = 1; i <= len - 1; i++) printf("%d", a[i]);
                printf("\n");
            }
            else { printf("0\n"); }
        }
        else { printf("0\n"); }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/zufezzt/p/5188489.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CodeForces - 616D是一个关于找到一个序列中最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段中不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]中不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当前数字在map中不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]中的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值