题目描述:
给出长度为
n
n
n的序列
a
i
a_i
ai,选出最少的数(非空)使得它们的
g
c
d
gcd
gcd为
1
1
1
n
,
a
i
≤
3
∗
1
0
5
n,a_i\le3*10^5
n,ai≤3∗105,无解输出
−
1
-1
−1
题目分析:
3
∗
1
0
5
3*10^5
3∗105以内质因子最多的数只有6个,而如果有解,考虑其中质因子最少的数
x
x
x,其余每个数一定囊括了一个不在
x
x
x中的质因子,且各自囊括的那个质因子不同,(相当于不断去掉gcd的因子)。也就是说答案最多是
x
x
x的质因子个数+1,也就是
7
7
7。
这张例子截自洛谷的题解:
那么枚举答案的个数
k
k
k,求出选出
k
k
k个数组成
g
c
d
=
1
gcd=1
gcd=1的方案
f
(
1
)
f(1)
f(1),只需要求出选出
k
k
k个数组成
g
c
d
gcd
gcd为
d
d
d的倍数的方案
F
(
d
)
F(d)
F(d),我们就可以通过容斥或莫比乌斯反演求出
f
(
1
)
f(1)
f(1)。
而
F
(
d
)
=
C
c
n
t
d
k
F(d)=C_{cnt_d}^k
F(d)=Ccntdk,
c
n
t
d
cnt_d
cntd表示
a
i
a_i
ai中为
d
d
d的倍数的数的个数。
由莫比乌斯反演有:
f
(
d
)
=
∑
d
∣
x
F
(
x
)
μ
(
x
d
)
f(d)=\sum_{d|x}F(x)\mu(\frac xd)
f(d)=∑d∣xF(x)μ(dx)
由容斥有:
f
(
d
)
=
F
(
d
)
−
∑
d
∣
x
f
(
d
)
f(d)=F(d)-\sum_{d|x}f(d)
f(d)=F(d)−∑d∣xf(d)
于是就做完了,复杂度 O ( n ln n ∗ 7 ) O(n\ln n*7) O(nlnn∗7)
Code:
#include<bits/stdc++.h>
#define maxn 300005
using namespace std;
const int mod = 998244353;
int n,a[maxn],mx,f[maxn],fac[maxn],inv[maxn];
int C(int n,int m){return n<m?0:1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
int main()
{
scanf("%d",&n);
for(int i=1,x;i<=n;i++) scanf("%d",&x),a[x]++,mx=max(mx,x);
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(int i=2;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=2;i<=n;i++) inv[i]=1ll*inv[i]*inv[i-1]%mod;
for(int i=1;i<=mx;i++)
for(int j=i+i;j<=mx;j+=i) a[i]+=a[j];
for(int k=1;k<=7;k++){
for(int i=mx;i>=1;i--){
f[i]=C(a[i],k);
for(int j=i+i;j<=mx;j+=i) f[i]=(f[i]-f[j])%mod;
}
if(f[1]) return printf("%d\n",k),0;
}
puts("-1");
}