给你一个网站你怎么做的/推广产品的文案
【gmoj】【欧拉函数】Gcd会不会
题目
解题思路
题目十分简单直白
就是求1~n内每个数与其他数的最大公因数的和
假设一个d能被 i 整除那么它的贡献如下
接着将 j/d 那么最大公因数也会 /d,贡献变成这样
然后我们想到欧拉函数
φ(i)意为1~i中有多少个数与 i 互质
那么式子就可以化为
为了节省时间我们可以预处理出所有的φ
可用线性筛o(n)求
不懂的小朋友戳这里
接着我们就枚举 i (所求值/因子) j (因子) ij 即为所求值
转移式即为 ans[ij]=phi[i]*j
最后用前缀和统计答案就好啦
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define max(a,b) (((a)>(b))?(a):(b))
using namespace std;
long long w,n,t,a[200100],p[1000100],prm[1000100],f[1000100],ans[100010];
int main()
{scanf("%lld",&w);for (int i=1;i<=w;i++){scanf("%lld",&a[i]);n=max(a[i],n); }f[1]=1;memset(p,0,sizeof(p));for (int i=2;i<=n;i++){ if (!p[i]) {f[i]=i-1; prm[++t]=i;}for (int j=1;j<=t&&i*prm[j]<=n;j++){p[i*prm[j]]=1;if (i%prm[j]==0){f[i*prm[j]]=f[i]*prm[j];break;} else f[i*prm[j]]=f[i]*(prm[j]-1);}}for (int i=2;i<=n;i++)for (int j=1;j<=n/i;j++)ans[i*j]+=f[i]*j;for (int i=2;i<=n;i++)ans[i]+=ans[i-1]; for (int i=1;i<=w;i++)printf("%lld %lld\n",ans[a[i]],a[i]);return 0;
}