[题解] AT_abc230_g [ABC230G] GCD Permutation
Monke_FClBrI · · 题解
大家好,我不会莫反,我是暴力老哥。
考虑给定序列
我们考虑本题就相当于做两次上面的东西套起来:先枚举一个值
但是直接做跑得很慢。考虑对每个
我们发现枚举倍数的这部分有两种方法:直接枚举
不会算复杂度,但是没怎么卡常就过了,时间
代码
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define SZ(x) (int)(x).size()
using namespace std;
const int N=2e5+5;
int n,a[N],d[N];
ll f[N],g[N],ans;
basic_string<int> ve[N];
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=2;i<=n;i++)
for(int j=i;j<=n;j+=i)
ve[j].pb(i);
for(int i=2;i<=n;i++){
int t=0;
for(int j=i;j<=n;j+=i)
for(int v:ve[a[j]])
if(!g[v]++)d[++t]=v;
sort(d+1,d+t+1);
for(int j=t;j;j--){
g[d[j]]=g[d[j]]*(g[d[j]]+1)/2;
if(n/d[j]<t-j)
for(int k=d[j]*2;k<=n;k+=d[j])
g[d[j]]-=g[k];
else for(int k=j+1;k<=t;k++)
if(d[k]/d[j]*d[j]==d[k])g[d[j]]-=g[d[k]];
f[i]+=g[d[j]];
}
for(int j=1;j<=t;j++)g[d[j]]=0;
}
for(int i=n;i>1;i--){
for(int j=i*2;j<=n;j+=i)
f[i]-=f[j];
ans+=f[i];
}
cout<<ans<<'\n';
return 0;
}
(逃