题解:CF1656H Equal LCM Subsets
题面
美妙多校讨论,带来新科技。
我们考虑如果我们已经把所有的
然后我们发现好像分解质因数是唯一的瓶颈。
现在我们考虑用其他题解说的线段树再仔细想想。
我们发现我们要的并不是把
结合 CF 大神的文章,我有一个可以大概在
我们考虑已经求出了一个前缀对应的
尝试证明复杂度(有错请指出):
首先,我们知道,这玩意最后找出来的数组长度不可能比所有
另外,我们记所有的数的总乘积为
其实感觉这个远远跑不满,如果有更严格的上界欢迎来写题解。
总复杂度
洛谷已有记录里第 3 优解。
代码:
#include<bits/stdc++.h>
#define int __int128
using namespace std;
char buf[1000005],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
int read(){
int x=0,f=0,c=gc();
while(!isdigit(c))f|=(c=='-'),c=gc();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=gc();
return f?-x:x;
}
char puf[1000005];
int ptot;
#define pc(x) putchar(x)
int num[45],ntot;
inline void print(int x){
if(x<0){
pc('-');
print(-x);
return;
}
ntot=0;
do{
num[ntot++]=x%10;
x/=10;
}while(x);
for(int i=ntot-1;i>=0;i--)pc(num[i]+48);
}
int T,n,m,tot,a[1005],b[1005],c[250005];
bool visa[1005],visb[1005];
void Insert(int x){//插数
for(int i=1;i<=tot;i++){
if(__gcd(x,c[i])!=1){//找到了
int d=__gcd(x,c[i]);
c[i]/=d;
x/=d;
if(d>1)Insert(d);
if(x>1)Insert(x);
return;
}
}
c[++tot]=x;//没找到
}
struct node{
int x,y;
bool operator<(const node &t)const{return x<t.x||(x==t.x&&y<t.y);}
bool operator>(const node &t)const{return x>t.x||(x==t.x&&y>t.y);}
bool operator==(const node &t)const{return x==t.x&&y==t.y;}
};
vector<node>x[1005],y[1005];
struct Heap{//堆维护
priority_queue<node>qa,ra;
void Push(node x){
qa.push(x);
}
void Erase(node x){
ra.push(x);
}
node Max(){
while(!qa.empty()&&!ra.empty()&&qa.top()==ra.top())qa.pop(),ra.pop();
if(qa.empty())return node({-1,-1});
return qa.top();
}
bool empty(){
return !(qa.size()-ra.size());
}
void clear(){
while(!qa.empty())qa.pop();
while(!ra.empty())ra.pop();
}
}qa[250005],qb[250005];
signed main()
{
T=read();
while(T--){
n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=m;i++)b[i]=read();
tot=0;
for(int i=1;i<=n;i++)Insert(a[i]),visa[i]=1;
for(int i=1;i<=m;i++)Insert(b[i]),visb[i]=1;
int Tt=0;
for(int i=1;i<=tot;i++)if(c[i]!=1)c[++Tt]=c[i];
tot=Tt;
for(int i=1;i<=tot;i++)qa[i].clear(),qb[i].clear();
for(int i=1;i<=n;i++){
x[i].clear();
int A=a[i];
for(int j=1;j<=tot;j++){
if(a[i]%c[j]==0){
int tmp=0;
while(a[i]%c[j]==0){
a[i]/=c[j];
tmp++;
}
x[i].push_back(node({j,tmp}));
qa[j].Push(node({tmp,i}));
}
}
a[i]=A;
}
for(int i=1;i<=m;i++){
y[i].clear();
int A=b[i];
for(int j=1;j<=tot;j++){
if(b[i]%c[j]==0){
int tmp=0;
while(b[i]%c[j]==0){
b[i]/=c[j];
tmp++;
}
y[i].push_back(node({j,tmp}));
qb[j].Push(node({tmp,i}));
}
}
b[i]=A;
}
bool f=0;
int X=n,Y=m;
while(X&&Y){
bool fff=1;
for(int i=1;i<=tot;i++){
if(qa[i].Max().x!=qb[i].Max().x){
fff=0;
if(qa[i].Max().x>qb[i].Max().x){
node tmp=qa[i].Max();
int id=tmp.y;
for(auto op:x[id]){
qa[op.x].Erase(node({op.y,id}));
}
visa[id]=0;
X--;
}
else{
node tmp=qb[i].Max();
int id=tmp.y;
for(auto op:y[id]){
qb[op.x].Erase(node({op.y,id}));
}
visb[id]=0;
Y--;
}
}
}
if(fff){
f=1;
pc('Y'),pc('E'),pc('S'),pc(10);
print(X),pc(' '),print(Y),pc(10);
for(int i=1;i<=n;i++){
if(visa[i]){
print(a[i]);pc(' ');
}
}
pc(10);
for(int i=1;i<=m;i++){
if(visb[i]){
print(b[i]);pc(' ');
}
}
pc(10);
break;
}
}
if(!f)pc('N'),pc('O'),pc(10);
}
return 0;
}