ABC230
C
不难发现
inline void check(int x,int y){
//case #1:
if(y==x+B-A) return (void)(cout<<'#');
//case #2:
if(y==-x+B+A) return (void)(cout<<'#');
//else
cout<<'.';
}
G
设函数(不是普通的莫比乌斯函数) \(\mu(d)=\begin{cases} 0,(1或有相同质数)\\1,(仅有奇数个不同质数)\\-1,(仅有偶数个不同质数) \end{cases}\)
质数指唯一分解下的质数
则有 \(\sum\limits_{d|n} \mu(d)=\begin{cases} 0,n=1 \\ 1,n \ge 2\end{cases}\)
证明:
设 \(n=p_1^{a_1}\times p_2^{a_2}\times...\times p_k^{a_k}\)
因为 \(\mu(p^a)=0\),所以我们只用考虑 \(n'=p_1\times p_2\times ... \times p_k\) 的情况。
不难发现,\(d\) 就是从这 \(k\) 个质数里面选出若干个数,所以我们枚举选出了几个数,有:
\(S=\mu(1)+\sum\limits_{i=1}^k\binom{k}{i}(-1)^{i+1}\)
\(=\mu(1)-\sum\limits_{i=1}^k\binom{k}{i}(-1)^i\)
\(=0-(-1+1)^k+1\)
\(=1\)
证毕。
所以有:
\(\sum\limits_{1\le i \le j\le N} [gcd(i,j)\ne 1且 gcd(p_i,p_j)\ne 1]=\sum\limits_{1\le i \le j\le N}\sum\limits_{a|gcd(i,j)} \mu(a) \sum\limits_{b|gcd(p_i,p_j)} \mu(b)\)
设 \(f(a,b,i,j)=\begin{cases}1,a|i,a|j,b|p_i,b|p_j\\0,其他情况\end{cases}\)
则 \(\sum\limits_{1\le i \le j \le N}\sum\limits^{N}_{a=1}\sum\limits_{b=1}^{N} \mu(a) \mu(b) f(a,b,i,j)\)
设 \(num\) 为满足 \(a|i,a|j,b|p_i,b|p_j\) 的数的个数
\(\therefore \sum\limits_{1\le i \le j \le N} f(a,b,i,j)=\binom{num+1}{2}\) (因为 \(i,j\) 可以相等,所以总点数 \(+1\) 表示可以自己选自己)
\(\therefore \sum\limits^{N}_{a=1}\sum\limits_{b=1}^{N} \mu(a) \mu(b) \binom{num+1}{2}\)
因为 \(\mu (p^a)=0\),所以我们只用算那些只由不同素数相乘的 \(a,b\)。
我们考虑枚举所有 \(\mu(a)\ne 0\) 的 \(a\),\(O(\frac{N}{a})\) 的复杂度处理出 \(num\),并且发现要使 \(num\ne 0\),\(b\) 必须是 \(p_i\) 的约数且 \(\mu(b)\ne 0\)。因为 \(2⋅3⋅5⋅7⋅11⋅13⋅17=510510>200000\),所以这样枚举 \(b\),复杂度为 \(2^6-1=63\),总时间复杂度为 \(O(\sum\limits_{a=1}^N63\frac{N}{a}\approx 63NlogN)\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,p[N],ans;
int amu[N],pr[N],cnt,num[N];
bool v[N];
int vis[N];
vector<int> M,S,d[N];
inline void init(){
for(int i=2;i<=n;++i){
if(!v[i]) pr[++cnt]=i,amu[i]=1;
for(int j=1;j<=cnt&&pr[j]*i<=n;++j){
v[pr[j]*i]=1;
if(i%pr[j]==0) break;
amu[pr[j]*i]=-amu[i];
}
if(amu[i]!=0){
M.push_back(i);
for(int j=i;j<=n;j+=i) d[j].push_back(i);
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
init();
for(int i=1;i<=n;++i) cin>>p[i];
for(auto a:M){
for(int i=a;i<=n;i+=a){
for(auto j:d[p[i]]){
++num[j];
if(!vis[j]) vis[j]=1,S.push_back(j);
}
}
for(auto b:S)
ans+=amu[a]*amu[b]*(num[b]+1)*num[b]/2,num[b]=vis[b]=0;
S.clear();
}
cout<<ans<<endl;
return 0;
}