题解:CF1912E【保姆级】

【CF1912E】 Evaluate It and Back Again【保姆级】

前言

  • 博客食用更佳~

与楼中的大佬思路相同,有借鉴之处,但本蒻蒟这篇 还算详细,这是来自蒻蒟的发言,不要在意...

前置思维

  • 构造。

分析

使得正着读它的结果是 \(p\),倒着读它的结果是 \(q\)
我们可以想到,让这个式子由两部分构成:

  1. 正着读可以算出 \(p\) 的值(部分一)。
  2. 反着读可以算出 \(q\) 的值(部分二)。

这便是 思路

  1. 部分一:反着读的值为零。
  2. 部分二:正着读的值为零。

这样的话,本题似乎只需要用到加法和减法!
如果你有了思路,此灵感会祝你 AC 本题!
具体下面分晓!

构码思路

正读为 p 反读为 0(核心)

我们可以想象一种构造:
偶数 考虑!

\[0 + k + k - 0 \]

这样的话,正着读的贡献为 \(2k\),反着读贡献为 \(0\)(对 \(p\) 而言)。

相反 \(q\) 的构造便是:

\[0 - k + k + 0 \]

这样的话,正着读的贡献为 \(0\),反着读贡献为 \(2k\)(对 \(p\) 而言)。

我们便可以得到以下 \(code\)

Code

p /= 2; q /= 2;
//p
if(p > 0) printf("0+%lld+%lld-0+", p, p);
else printf("0%lld%lld+0+", p, p);
//q
q = fzs(q);//翻转数字
if(q > 0) printf("0-%lld+%lld+0", q, q);
else printf("0+%lld%lld-0", -q, q);

翻转数字

emmm...这部分显而易见,开辟一个 \(f = 1\),在原数字除 \(10\) 的同时,\(f\)\(10\) 加上扣下来的数。
我想 \(code\) 更可以说明方法!

code

lt fzs(lt n){//翻转数字
    lt f = 0;
    while(n){
        f = f*10 + n%10;
        n /= 10;
    }
    return f;
}

其它细节

如果是奇数,\(2k\)的方法会出现问题,但是我们可以用 拆数 的方式进行构造!!!
那怎么拆?我们可以灵活应用 \(12\)\(21\) 相反且一奇一偶的特点:

  1. 如果均为奇数:我们只需要在序列前加上 \(0+1+0\),然后构造 \(p-1\)\(q-1\)
  2. \(p\) 为奇数:我们只需要在序列前加上 \(0+21+0\),然后构造 \(p-21\)\(q-12\)
  3. \(q\) 为奇数:我们只需要在序列前加上 \(0+12+0\),然后构造 \(p-12\)\(q-21\)

小小的BUG

我们考虑害怕 \(q\)\(p\) 翻转后会出现前导零的错误!!!
所以我们可以通过 \(0+2+0\) 的方式构造剩余!!!注意用 while 更为保险!

Code

//害怕出现q翻转后结尾为零
while(p%10 == 0 || q%10 == 0){
    p -= 2, q -= 2;
    printf("0+2+0+");
}

最后完整 \(code\) 放下面了,里面有注释,助力你 AC 本题!

CODE

#include<bits/stdc++.h>
using namespace std;

typedef long long lt;
lt p, q;
bool pf, qf;//f判断奇偶

lt fzs(lt n){//翻转数字
    lt f = 0;
    while(n){
        f = f*10 + n%10;
        n /= 10;
    }
    return f;
}

int main(){
    scanf("%lld%lld", &p, &q);
    if(p % 2) pf = 1; if(q % 2) qf = 1;

    //p, q均为奇
    if(pf && qf){
        printf("0+1+0+");
        p -= 1; q -= 1;
    }
    //p为奇
    else if(pf){
        printf("0+21+0+");
        p -= 21; q -= 12;
    }
    //q为奇
    else if(qf){
        printf("0+12+0+");
        p -= 12; q -= 21;
    }

    //害怕出现q翻转后结尾为零
    while(p%10 == 0 || q%10 == 0){
        p -= 2, q -= 2;
        printf("0+2+0+");
    }

    //开整!
    p /= 2; q /= 2;
    //p
    if(p > 0) printf("0+%lld+%lld-0+", p, p);
    else printf("0%lld%lld+0+", p, p);
    //q
    q = fzs(q);
    if(q > 0) printf("0-%lld+%lld+0", q, q);
    else printf("0+%lld%lld-0", -q, q);
    return 0;
}
//正读有贡献,反着无: 0+k+k-0
//反读有贡献,正着无: 0-k+k+0

后记

  • 点赞加关注,AK不迷路!
posted @ 2024-07-15 20:54  元越  阅读(10)  评论(2编辑  收藏  举报