CF1986G2 Permutation Problem (Hard Version)
Question 问题 CF1986G2 Permutation Problem (Hard Version)
难度:
给定一个
数据范围
Analysis 思路分析
首先对于
发现该形式可以写作
也就是令
Solution 数学
感觉整体的思路就是
最初的想法是维护一个二维数组 map 维护,最坏的情况下空间会因为 map 被插入内容过大而爆炸,这也是很多人在此题 128MiB 的限制下 MLE 了。
考虑如何优化,我们会发现
或者换一种方式思考,我们当前先枚举
我们预处理出该
在最后,由于本题询问的是有序二元组,以上做法并没有考虑
记得清空。
时间复杂度:
因为
Code 代码
signed main(){
for(rint i=1;i<=N-7;i++) for(rint j=i;j<=N-7;j+=i) fac[j].pb(i);
read(T);
while(T--){
ans=0;
read(n);
for(rint i=1,t;i<=n;i++){
read(t);
int x=i/__gcd(i,t),y=t/__gcd(i,t);//除去 gcd
a[x].pb(y);b[y].pb(x);//建立双射,有利于计算答案
if(x==1) ans--;//对于 i=j 且 ai|bi 的情况提前减掉
}
for(rint i=1;i<=n;i++){
for(auto a1:a[i]) for(auto a2:fac[a1]) cnt[a2]++;//处理因数个数和
for(rint a2=i;a2<=n;a2+=i) for(auto b1:b[a2]) ans+=cnt[b1];//计算贡献
for(auto a1:a[i]) for(auto a2:fac[a1]) cnt[a2]=0;//清空
}
for(rint i=1;i<=n;i++) a[i].clear(),b[i].clear();//清空
cout<<ans/2<<endl;//注意有序,除以二
}
return 0;
}