質問表面:https://www.luogu.com.cn/problem/CF803F
トピックは意図:あなたの順序を与えるために、あなたはどのように多くのGCD = 1のサブシーケンスを聞いています
溶液:
我々は、F(X)を設定GCDサブシーケンス番号xを表します。明らかに、我々は、F(1)が必要です。
それは、シーケンス番号を祈るされているので、私たちは数字の順序を制御することはできません。
観察用X> 1、GCDケースがあること、1ではない、彼らは条件満たす
順序ですべての数字は、xの倍数です。
配置されたT [i]はiは複数の配列の出現の数を表し、これは、N-かもしれ\(\} N-SQRTは{\)が得られます。
しかし、これはf(x)のかどうかを請います。
それは何が良いを求めていますか?あなたは、xが数である複数のサブシーケンスを見つけた場合、追求することをお勧めします。
提供G(x)はxのみからなる複数の配列の有効なシーケンスの数を表します。これは、直接O(1)要求することができ、
G(X)= \(2 ^ {T [X]} \) -1。
見つかりました:次に、裏FおよびGの関係を研究するために\(1 G = F * \)
メビウスでの反転と、$ fを描くことができる(N)= \(\ {N-sum_ | D} \) G(D)
したがって、F(1)要求が非常に良好です。SIFT (\ \ MU \)のような関数〜
O(N-の複雑\(\ N-SQRT {} \) )
コード:
#include<bits/stdc++.h>
using namespace std;
#define re register ll
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline ll
template<class D>I read(D &res){
res=0;register D g=1;register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')g=-1;
ch=getchar();
}
while(isdigit(ch)){
res=(res<<3)+(res<<1)+(ch^48);
ch=getchar();
}
res*=g;
}
const ll Mod=1e9+7;
ll n,m,ans,v[101000],twice[101000],a[101000],t[101000],prime[101000],tot,mu[101000];
int main(){
read(n);
F(i,1,n)read(a[i]);
F(i,1,n){
F(j,1,sqrt(a[i])){
if(a[i]%j==0){
t[j]++;
if(j*j!=a[i])t[a[i]/j]++;
}
}
}
tot=0;mu[1]=1;twice[0]=1;
F(i,1,100000)twice[i]=twice[i-1]*2ll%Mod;
F(i,2,100000){
if(!v[i])prime[++tot]=i,mu[i]=-1;
F(j,1,tot){
if(i*prime[j]>100000)break;
v[i*prime[j]]=1;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
F(i,1,100000)ans=(ans+(ll)(twice[t[i]]-1)*mu[i]+Mod)%Mod;
printf("%lld",ans);
return 0;
}