Greater Integer, Better LCM | 2021牛客暑期多校训练营5 给你
a
,
b
,
c
a,b,c
a,b,c ,你需要找到一对
x
,
y
x,y
x,y ,满足:
l
c
m
(
a
+
x
,
b
+
y
)
=
c
lcm(a+x,b+y)=c
lcm(a+x,b+y)=c 你需要输出最小的满足的
x
+
y
x+y
x+y 的值 注意,这里给出的
c
c
c 的形式为
∏
i
=
1
n
p
i
q
i
\prod_{i=1}^n p_i^{q_i}
∏i=1npiqi
1
≤
n
≤
18
1\le n \le 18
1≤n≤18
1
≤
a
,
b
,
c
≤
1
0
32
1\le a,b,c\le 10^{32}
1≤a,b,c≤1032
∑
q
i
≤
18
\sum q_i\le 18
∑qi≤18
思路
首先注意一下,
a
,
b
,
c
a,b,c
a,b,c 之大,大到
l
o
n
g
l
o
n
g
long\ long
longlong 存不下,后面都用
i
n
t
128
int128
int128 存储与计算 加法性质对于
p
x
p^x
px 的影响比较复杂,我们考虑把问题转换成:
l
c
m
(
x
,
y
)
=
c
x
≥
a
,
y
≥
b
lcm(x,y)=c\qquad x\ge a,y\ge b
lcm(x,y)=cx≥a,y≥b 这样,我们需要最小化
x
+
y
x+y
x+y 的问题依然没有变化(两个数都加了常数)
对于
c
=
∏
p
i
q
i
c=\prod p_i^{q_i}
c=∏piqi ,看
n
n
n 很小,我们自然可以状压去暴力枚举哪一个数字取到了
q
i
q_i
qi ,即状态为
S
S
S 那么,假设某一位为
0
0
0 ,表示这个数字这一位没有取到
p
i
q
i
p_i^{q_i}
piqi,但是可以取到
p
i
0
∼
p
i
q
i
−
1
p_i^0\sim p_i^{q_i-1}
pi0∼piqi−1 次 考虑到
∑
q
i
≤
18
\sum q_i\le 18
∑qi≤18 ,我们仍然可以去暴力
d
f
s
dfs
dfs ,每一位取几次都爆搜 然后去记录一下,是
S
S
S 的状态,且大于等于
a
a
a 的数字
x
x
x 的最小值
d
p
a
[
S
]
dpa[S]
dpa[S] ; 是
S
S
S 的状态,且大于等于
b
b
b 的数字
y
y
y 的最小值
d
p
b
[
S
]
dpb[S]
dpb[S]
然后注意到:如果
T
T
T 是
S
S
S 的超集(也就是
S
&
T
=
S
S\&T=S
S&T=S),且
d
p
a
[
T
]
<
d
p
a
[
S
]
dpa[T]<dpa[S]
dpa[T]<dpa[S],那么我们明显取
d
p
a
[
T
]
dpa[T]
dpa[T] 是更优的,也就是我们需要取
S
S
S 的 超集的最小值
最后,我们需要获得的答案就是:
d
p
[
S
]
+
d
p
[
T
]
−
a
−
b
dp[S]+dp[T]-a-b
dp[S]+dp[T]−a−b ,其中
S
∣
T
=
全
集
S|T=全集
S∣T=全集
代码
时间复杂度:
O
(
n
×
2
n
)
O(n\times 2^n)
O(n×2n)
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =1e6+50;constint MOD =998244353;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;
ll qpow(ll a,ll n){/* */ll res =1LL;while(n){if(n&1)res=res*a%MOD;a=a*a%MOD;n>>=1;}return res;}
ll qpow(ll a,ll n,ll p){a%=p;ll res =1LL;while(n){if(n&1)res=res*a%p;a=a*a%p;n>>=1;}return res;}
ll npow(ll a,ll n){/* */ll res =1LL;while(n){if(n&1)res=res*a;a=a*a;n>>=1;if(res<0||a<0)return0;}return res;}
ll inv(ll a){/* */returnqpow(a,MOD-2);}
ll inv(ll a,ll p){returnqpow(a,p-2,p);}int n;
lll a,b;
lll p[30],q[30];
lll dpa[1<<19],dpb[1<<19];voiddfs(int x,int S,lll sum){if(sum >= a)dpa[S]=min(dpa[S],sum);if(sum >= b)dpb[S]=min(dpb[S],sum);if(x == n)return;dfs(x+1,S,sum);for(int i =1;i < q[x];++i){
sum *= p[x];dfs(x+1,S,sum);}
sum *= p[x];dfs(x+1,S|(1<<x),sum);}intmain(){
n =read();for(int i =0;i < n;++i)p[i]=read_lll(),q[i]=read_lll();
a =read_lll(),b =read_lll();memset(dpa,0x3f,sizeof(dpa));memset(dpb,0x3f,sizeof(dpb));dfs(0,0,1);int ed =(1<<n)-1;for(int i = ed;i >=0;--i){for(int j =0;j < n;++j){if(i &(1<<j)){
dpa[i ^(1<<j)]=min(dpa[i ^(1<<j)],dpa[i]);
dpb[i ^(1<<j)]=min(dpb[i ^(1<<j)],dpb[i]);}}}
lll ans;memset(&ans,0x3f,sizeof(ans));for(int i =0;i <= ed;++i)ans =min(ans,dpa[i]+ dpb[ed-i]- a - b);Print(ans);Write();return0;}