标签:gcd 前缀 匹配 clu 欧拉 name nbsp ++ stream
想了一下就秒了
大概算是欧拉函数里比较好想的题了
直接考虑$gcd(x,y) = 1$
因为互质就满足性质$gcd(x * p,y * p) = p$
所以就可以转化成欧拉函数了,就是求出互质对数然后对合法的素数匹配一下就行了
可以用前缀和优化
对于质数的处理我是直接在求欧拉函数的时候筛的
所以复杂度是$O(nloglogn)$的,但是不开O2貌似跑不过
楼下几位dalao的复杂度我不是很会算,不知道有没有dalao能解释一下
#include <cstdio> #include <ctype.h> #include <cstdlib> #include <iostream> #include <algorithm> #include <cmath> using namespace std; template <typename T> inline T read(T &f){ f = 0; int x = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) x = -1; c = getchar(); } while(isdigit(c)) f = (f << 1) + (f << 3) + c - ‘0‘,c = getchar(); return f = f * x; } #define LL long long const int maxn = 10000000 + 5; int n,tot; LL S[maxn]; LL pri[maxn],phi[maxn]; LL ans; void phi_table(){ phi[1] = 1; for(int i = 2;i <= n;i ++) if(!phi[i]){ pri[++ tot] = i; for(int j = i;j <= n;j += i){ if(!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i - 1); } } } int main(){ read(n); phi_table(); for(int i = 1;i <= n;i ++) S[i] = S[i - 1] + phi[i]; for(int i = 1;i <= tot;i ++) ans = ans + (S[n / pri[i]] << 1) - 1; printf("%lld\n",ans); return 0; }
标签:gcd 前缀 匹配 clu 欧拉 name nbsp ++ stream
原文地址:http://www.cnblogs.com/lin1043/p/7593505.html