2022 CCPC Harbin D Math master
题面描述:
给你两个数 p , q p,q p,q,你可以有以下操作:
设 p p p 的十进制表达为 p 1 ′ p 2 ′ … p_{1}^{'} p_{2}^{'} \dots p1′p2′… ,q的十进制表达为 q 1 ′ q 2 ′ … q_{1}^{'} q_{2}^{'} \dots q1′q2′…
你可以选择任意几对 ( 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;
}