Files
luogu/solutions/CF1912E.md
T

3.2 KiB

CF1912E Evaluate It and Back Again题解

题意

给定两个数,要求你写出一个只包含数字, +, \times, - 的式子,正着看是第一个数,反着看是第二个数。

题解

观察发现只有一位数+, \times单项式倒过来读还是一样的,由 -0 结尾的单项式倒过来读和原式结果相反。

发现可以将一个要求倒着读后数值不变的数表示为 9 进制的形式,这样多项式中每一项都是倒着读后不变的。

  • 对于两个奇偶性相同的数,可以求两个数的平均数,将 p, q 分别表示为 p = \overline{pq} + \frac{p - q}{2}, q = \overline{pq} - \frac{p - q}{2}
  • 对于两个奇偶性不同的数,也可以求平均数,但是为了让 p, q 奇偶性统一,需要给 p, q 分别减去一个正着读是奇数,反着读是偶数的数,如 $12$,然后即可按照第一种形式做

然后就是注意特判两个相同的数和 0 0 的情况,别忘记开 long long 就结束了

不懂看注释

参考代码

#include <bits/stdc++.h>
using namespace std;
string ans;
string to_9(long long n) //转换为正反均相同的多项式
{
    bool flag = n >= 0;
    if (!flag)
        n = -n;
    ans = "";
    long long cnt = 0;
    long long yu[20] = {};
    while (n >= 10ll)
        yu[cnt++] = n % 9ll, n /= 9ll;
    yu[cnt] = n;
    if (!flag)
        ans += "0-";
    for (long long i = 0; i <= cnt; ++i)
    {
        if (yu[cnt - i] != 0)
        {
            for (long long j = 0; j < cnt - i; ++j)
                ans += "9*";
            ans += yu[cnt - i] + '0';
            if (flag)
                ans += "+0+";
            else
                ans += "-0-";
        }
    }
    while (ans[ans.size() - 1] == '+' || ans[ans.size() - 1] == '-')
        ans.pop_back(); // 去掉多于符号
    return ans;
}
string to_9_0(long long n) // 转换为正反读相反的多项式
{
    bool flag = n >= 0;
    if (!flag)
        n = -n;
    ans = "";
    long long cnt = 0;
    long long yu[20] = {};
    while (n >= 10)
    {
        yu[cnt++] = n % 9ll;
        n /= 9ll;
    }
    yu[cnt] = n;
    if (!flag)
        ans += "0-";
    for (long long i = 0; i <= cnt; ++i)
    {
        if (yu[cnt - i] != 0)
        {
            for (long long j = 0; j < cnt - i; ++j)
                ans += "9*";
            ans += yu[cnt - i] + '0';
            if (flag)
                ans += "-0+";
            else
                ans += "+0-";
        }
    }
    while (ans[ans.size() - 1] == '+' || ans[ans.size() - 1] == '-')
        ans.pop_back(); // 去掉多于符号
    return ans;
}
int main()
{
    long long p = 0, q = 0;
    scanf("%lld%lld", &p, &q);
    if (abs(p) % 2 == abs(q) % 2) // 同奇偶
    {
        long long _pq = p + q >> 1, p_q = p - _pq;
        if (p == 0 && q == 0) // 特判
        {
            puts("0");
            return 0;
        }
        cout << to_9(_pq) << ((_pq != 0 && p_q != 0) ? "+" : "") << to_9_0(p_q) << endl;
    }
    else // 异奇偶
    {
        long long _pq = (p - 21 + q - 12) >> 1, p_q = p - 21 - _pq; // 转换为同奇偶
        cout << to_9(_pq) << ((_pq != 0 && p_q != 0) ? "+" : "") << to_9_0(p_q) << ((p_q != 0 || _pq != 0) ? "+" : "") << "21" << endl;
    }
    return 0;
}