2021牛客暑期多校训练营5 G.Greater Integer, Better LCM(搜索,子集合并)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营5 G.Greater Integer, Better LCM(搜索,子集合并)相关的知识,希望对你有一定的参考价值。
l c m ( a + x , b + y ) lcm(a+x,b+y) lcm(a+x,b+y)的意义就是对于每个质因子幂取 a + x a+x a+x和 b + y b+y b+y中更大的那个
而且 a + x a+x a+x和 b + y b+y b+y在每个质因子上,至少一个是最高次幂,这才能满足 l c m ( a + x , b + y ) = c lcm(a+x,b+y)=c lcm(a+x,b+y)=c
考虑枚举 a + x a+x a+x和 b + y b+y b+y在每个质因子取到的幂次,复杂度是不超过 O ( 2 ∑ q i ) O(2^{\\sum\\limits q_i}) O(2∑qi)
这些状态我们可以爆搜出来,同时用一个二进制数表示这些状态在哪些质因子取到最高次幂
于是定义 f [ i ] f[i] f[i]表示当质因子限制状态为 i i i时的大于 a a a的最小值
定义 g [ i ] g[i] g[i]表示质因子限制状态为 i i i时大于 b b b的最小值
于是可以暴力枚举 f [ i ] f[i] f[i]和 g [ j ] g[j] g[j]若满足 i ∣ j = 2 ∑ q i − 1 i|j=2^{\\sum q_i}-1 i∣j=2∑qi−1可以更新答案
这样的复杂度是 2 ∑ q i ∗ 2 ∑ q i 2^{\\sum q_i}*2^{\\sum q_i} 2∑qi∗2∑qi
如果枚举 f [ i ] f[i] f[i]后继续枚举 i ⊕ ( 2 ∑ q i − 1 ) i\\oplus (2^{\\sum q_i}-1) i⊕(2∑qi−1)的子集可以做到 3 n 3^{n} 3n的复杂度
还是不太能过的样子,考虑让 f [ i ] f[i] f[i]表示所有包含子集 i i i的状态中的最小值, g g g同理
利用子集 d p dp dp的思想,每次只更新子集的极大真子集,更小的子集会被极大真子集更新
总体复杂度 O ( n ∗ 2 n ) O(n*2^n) O(n∗2n)
#include<bits/stdc++.h>
using namespace std;
using i128 = __int128;
const int maxn = (1<<20);
const i128 inf = 1e36;
i128 in()
{
static char buf[110]; i128 x = 0; scanf("%s", buf);
for (char *p = buf; *p; ++p) x = x * 10 + (*p - '0');
return x;
}
void out( i128 x )
{
if (x >= 10) out(x / 10);
putchar('0' + x % 10);
}
inline i128 min(i128 x,i128 y){ return x<y?x:y; }
int n,mx,p[maxn],q[maxn];
i128 a,b,f[maxn],g[maxn];
void dfs(int id,i128 x,int val)
{
if( x>=a ) f[val] = min( f[val],x );
if( x>=b ) g[val] = min( g[val],x );
if( id>n ) return;
for(int i=0;i<=q[id];i++)
{
dfs( id+1,x,val | ( (i==q[id])*(1<<(id-1)) ) );
x *= p[id];
}
}
void zjdp()
{
for(int i=mx;i>=0;i--)
for(int j=0;j<n;j++)
{
if( ((i>>j)&1)==0 ) continue;
f[i^(1<<j)] = min( f[i^(1<<j)],f[i] );
g[i^(1<<j)] = min( g[i^(1<<j)],g[i] );
}
}
int main()
{
cin >> n; mx = (1<<n)-1;
for(int i=0;i<=mx;i++) f[i] = g[i] = inf;
for(int i=1;i<=n;i++) cin >> p[i] >> q[i];
a = in(); b = in();
dfs( 1,1,0 ); zjdp();
i128 ans = inf;
for(int i=mx;i>=0;i--)
ans = min( ans,f[i]+g[mx^i]-a-b );
out( ans );
}
以上是关于2021牛客暑期多校训练营5 G.Greater Integer, Better LCM(搜索,子集合并)的主要内容,如果未能解决你的问题,请参考以下文章