Codeforces 1687E. Become Big For Me (3500)

给定 \(n\) 个正整数 \(a_1,\ldots,a_n\),构造 \(k_1+k_2\) 个连续子序列 \(b_1,\ldots ,b_{k_1},c_1,\ldots ,c_{k_2}\),满足
\(1.\) \(\sum {|b_i|}+\sum {|c_i|}\le 10^6\)
\(2.\) \(\frac{\prod \text{lcm}(b_i)}{\prod \text{lcm}{(c_i)}}=\gcd\limits_{i\neq j}\{a_ia_j\}\)
\(1\le n\le 10^5,1\le a_i\le 10^6,\) 保证有解。


根据广义 \(\min-\max\) 容斥,有

\[\text{kth}\min(S)=\sum_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\max(T) \]

可得

\[\gcd_{i\ne j}\{a_ia_j\}=\prod_{T\subset S}\operatorname{lcm}(T)^{(-1)^{|T|}(|T|-2)} \]

那么就可以用 \(O(n2^n)\) 次表示出 \(\gcd\limits_{i\neq j}\{a_ia_j\}\)


显然这是不够快的,考虑用 \(T\subseteq S=\{a_1,\ldots,a_n\}\) 代替 \(S\),只需要满足 \(\gcd\limits_{x,y\in T,x\neq y}\{xy\}=\gcd\limits_{i\neq j}\{a_ia_j\}\)

计算一下,满足连续子序列数 \(\le 10^5\) 的最大的 \(|T|\)\(14\),所以只要在 \(S\) 中找到 \(\le 14\) 个数使得条件满足。

首先在质因子方面考虑 \(\gcd\limits_{i\neq j}\{a_ia_j\}\),也就是保留了每个质数 \(p\) 的幂次的最小值和次小值。

设原序列的 \(V=\gcd\limits_{i\neq j}\{a_ia_j\}\),那么直接对 \(V\) 分解质因数,保留每个质数 \(p\ (p|V)\) 的幂次的最小值和次小值的数,由于值域 \(\le 10^6\),那么暂时最多保留 \(14\) 个数,刚好卡到上界。

但此时可能会出现一个问题,就是使得一些不是 \(V\) 的因数的质数 \(p\) 也算进 \(\gcd\limits_{i\neq j}\{a_ia_j\}\),所以对于每个这样的质数 \(p\),在原序列中找到一个没有加入 \(T\) 且不能被 \(p\) 整除的数加进来使得条件满足。不难证明最多只需要加一次,此时保留的数最多有 \(15\) 个。


\(\color{green}{\text{observation:}}\)
\(n>14\) 时,一定能删除序列中的一个数使得 \(\gcd\limits_{i\neq j}\{a_ia_j\}\) 不变。
\(\textbf{P.f.}\)
假设删除序列中的任意一个数都会改变 \(\gcd\limits_{i\neq j}\{a_ia_j\}\),那么对于序列中的每个数 \(x\),都存在一个质数 \(p\) 使得 \(x\)\(p\) 的幂次严格前二大。
因为 \(n>14\),所以这样的质数 \(p\) 至少有 \(\lceil\frac{n}{2}\rceil\geq 8\) 个。且如果存在这样的质数 \(p\),那么序列中至少 \(n-2\) 个数都能被 \(p\) 整除,此时需要满足 \((\prod p_i)^{n-2}\le (\max \{a_i\})^n\)。最小的 \(8\) 个质数是 \(2,3,5,7,11,13,17,19\),不满足。因此假设自相矛盾,原命题成立。

根据这个结论,直接枚举 \(T\) 中哪个数被删去即可。

\(\color{blue}{\text{code}}\)

#include<bits/stdc++.h>
#define fi first
#define se second
#define eb emplace_back
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5;
int n,a[N],in[N],I[M];ll mul=1;
vector<int>v[M],V,S,U;vector<pair<int,int> >ans,vc;
inline ll qpow(ll a,int b){ll ans=1;for(;b;b>>=1,a*=a)if(b&1)ans*=a;return ans;}
inline ll calc(vector<int>S){
	ll ans=0;for(auto p:S)for(auto q:S)if(p^q)ans=__gcd(ans,(ll)a[p]*a[q]);return ans;
}
int main(){
	for(int i=2;i<M;++i)if(v[i].empty())
		for(int j=i;j<M;j+=i)v[j].eb(i);
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",a+i);
	for(int j=2;j;--j)for(auto p:v[a[j]]){
		int u=0;
		for(int i=1;i<=n;++i)u+=(a[i]%p>0);
		if(u<2&&!I[p])V.eb(p),I[p]=1;
	}
	for(auto p:V){
		vc.clear();
		for(int i=1;i<=n;++i){int cnt=0;for(int x=a[i];x%p==0;x/=p)++cnt;vc.eb(make_pair(cnt,i));}
		sort(vc.begin(),vc.end());
		for(int i=1;~i;--i)if(!in[vc[i].se])S.eb(vc[i].se),in[vc[i].se]=1;
		mul*=qpow(p,vc[0].fi+vc[1].fi);
	}
	ll q=calc(S)/mul;
	if(q){for(int i=2;i<M;++i)if(q%i==0&&v[i].size()==1&&v[i][0]==i){while(q%i==0)q/=i;U.eb(i);}}
	for(auto p:U){
		int t=0;for(auto o:S)t+=(a[o]%p>0);
		while(t<2){for(int i=1;i<=n;++i)if(!in[i]&&a[i]%p>0){in[i]=1,S.eb(i);break;}++t;}
	}
	while(S.size()>14){
		for(auto del:S){
			vector<int>T;
			for(auto id:S)if(id^del)T.eb(id);
			if(calc(S)==calc(T)){S=T;break;}
		}
	}
	int m=S.size();sort(S.begin(),S.end());
	for(int T=1;T<1<<m;++T){
		int sz=__builtin_popcount(T),w=(sz&1?-1:1)*(sz-2);
		while(w>0)ans.push_back({0,T}),w--;
		while(w<0)ans.push_back({1,T}),w++;
	}
	printf("%d\n",ans.size());
	for(auto i:ans){
		printf("%d %d ",i.fi,__builtin_popcount(i.se));
		for(int j=0;j<m;++j)if((i.se>>j)&1)printf("%d ",S[j]);puts("");
	}
}
posted @ 2022-06-11 13:44  Samsara-soul  阅读(27)  评论(0编辑  收藏  举报