2022 CCPC Harbin D Math master

2022 CCPC Harbin D Math master

题面描述:

给你两个数 p , q p,q p,q,你可以有以下操作:

p p p 的十进制表达为 p 1 ′ p 2 ′ … p_{1}^{'} p_{2}^{'} \dots p1p2 ,q的十进制表达为 q 1 ′ q 2 ′ … q_{1}^{'} q_{2}^{'} \dots q1q2

你可以选择任意几对 ( i , j ) (i,j) (i,j)且满足 p i = q j p_{i}=q_{j} pi=qj并将他们从原数中删除,且变换之后的 ( a , b ) (a,b) (a,b)满足 a b = p q \frac{a}{b}=\frac{p}{q} ba=qp,求使得分子长度最小的变换方法

基本思路:

考虑到 2 63 2^{63} 263 的十进制位数不会超过 20 20 20 位,故考虑进行状态压缩,用二进制数表示每一位取或不取的情况,得到 a a a后,用 a b = p q \frac{a}{b}=\frac{p}{q} ba=qp的等式求出 b b b,检查 b b b是否是合法操作得来,若合法,则更新答案

另外, c h e c k check check 时需要考虑前导0,实现细节见代码

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long int
#define endl '\n'
#define Paddi ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
int tonum(string x)
{
    int ans = 0;
    for (int i = 0; i < x.size(); i++)
        ans = ans * 10 + (x[i] - '0');
    return ans;
}
signed main()
{
    Paddi;
    int T;
    cin >> T;
    while (T--)
    {
        string sp, sq;
        cin >> sp >> sq;
        int p = tonum(sp), q = tonum(sq);
        pair<int, int> ans = {p, q};
        int g = __gcd(p, q);
        p /= g, q /= g;
        int szp = sp.size(), szq = sq.size();
        for (int i = 0; i < (1ll << szp); i++)
        {
            bitset<25> s(i);
            vector<int> delp(15);
            int a = 0;
            for (int j = 0; j < szp; j++)
            {
                if (s[j] == 1)
                    a = a * 10 + sp[j] - '0';
                else if (s[j] == 0)
                    delp[sp[j] - '0']++;
            }
            if (a == 0 or (a % p) != 0)
                continue;
            int b = a / p * q;
            int tb = b;
            for (int j = sq.size() - 1; j >= 0; j--)
            {
                if ((sq[j] - '0') == (tb % 10))
                    tb /= 10;
                else
                    delp[sq[j] - '0']--;
            }
            bool can = true;
            for (int j = 0; j < 10; j++)
            {
                if (delp[j] != 0)
                    can = false;
            }
            if (can)
                ans.first = min(ans.first, a), ans.second = min(ans.second, b);
        }
        cout << ans.first << " " << ans.second << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值