题目链接
https://www.luogu.org/problemnew/show/P2568
分析
题目即求$\sum_{i=1}^N \sum_{j=1}^N [gcd(i,j)$ $is$ $a$ $prime$ $number$ $]$
我们提出这个素数变成$\sum_p \sum_{i=1}^{\frac{N}{p} \ } \sum_{j=1}^{\frac{N}{p} \ } [gcd(i,j)$ $is$ $1]$
对于后面两个$sigma$,考虑$i>=j$和$i<j$两种情况,不难想到答案为$2 * (\sum_{i=1}^{\frac {N}{P} \ }\phi(i))-1$,因为$i=j=1$时多算了种情况
于是求欧拉函数表同时前缀和就好了
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <cctype> #include <iostream> #define ll long long #define ri register int using std::min; using std::max; template <class T>inline void read(T &x){ x=0;int ne=0;char c; while(!isdigit(c=getchar()))ne=c=='-'; x=c-48; while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48; x=ne?-x:x;return ; } const int inf=0x7fffffff; int pri[1000005],tot=0; ll phi[10000007]; int n; inline void get_phi(){ bool vis[10000005]; memset(vis,0,sizeof(vis)); vis[1]=1,phi[1]=1; for(ri i=2;i<=n;i++){ if(!vis[i]){pri[++tot]=i,phi[i]=i-1;} for(ri j=1;j<=tot&&pri[j]*i<=n;j++){ vis[i*pri[j]]=1; if(i%pri[j]==0){phi[i*pri[j]]=phi[i]*pri[j];break;} else phi[i*pri[j]]=phi[i]*phi[pri[j]]; } } for(ri i=2;i<=n;i++)phi[i]+=phi[i-1]; return ; } ll ans=0; int main(){ read(n); get_phi(); for(ri i=1;i<=tot&&pri[i]<=n;i++){ ans+=(phi[n/pri[i]]<<1)-1; } printf("%lld\n",ans); return 0; }
|