GCD SUM
P2398 GCD SUM
解法1. 筛出来欧拉数后暴力搜 80分(实在卡不过去最后俩点了)
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; typedef long long LL; int primes[N], cnt; bool st[N]; int phi[N]; LL temp; bool fuck[N]; inline void get_primes(int n) //phi数组 { // phi[1] = 1; for(int i = 2; i <= n; i++) { if(!st[i]) { primes[cnt++] = i; phi[i] = i - 1; } for(int j = 0; primes[j] * i <= n; j++) { st[primes[j] * i] = true; if(i % primes[j] == 0) { phi[primes[j] * i] = phi[i] * primes[j]; break; } phi[primes[j] * i] = phi[i] * (primes[j] - 1); } } } inline void dfs(int u, int v, int rem) { if(u == 1 || v >= cnt) return; for(int i = v; i < cnt && primes[i] <= u / 2; i++) //问题就是 如果剩下个数咋办。 if(u % primes[i] == 0 && !fuck[u % primes[i]]) dfs(u / primes[i], v, rem); // cout<<u<<endl; if(!fuck[u]) temp += phi[u] * (rem / u), fuck[u] = true; } signed main() { //预处理出来了质数数组,然后质数试除 时间复杂度1e5 * ln1e5 互质数直接欧拉函数处理 如果该数为质数便直接不用了 int n; cin>>n; get_primes(n); LL ans = 0;//1LL * n * (n + 1) / 2; for(register int i = 1; i <= n; i++) //ans加上每个数的互质个数(因为gcd互质数=1) 然后加上每个数的约数之和) { if(!st[i]) { temp += phi[i]; continue; } memset(fuck, false, sizeof fuck); dfs(i, 0, i); } ans += 2 * temp; ans += 1LL * n * (n + 1) / 2; cout<<ans<<endl; }
解法2: 筛出来欧拉函数后发现每个欧拉数被用了sum(1 ~ n/i)次 直接遍历1 ~ n 复杂度O(n) 100分 ''' 解法3:筛出数后数论分块 时间复杂度O(q√n) q是查询次数 代码等学会了后补TAT
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 47 48 49 50 51 52 | #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; typedef long long LL; int primes[N], cnt; bool st[N]; int phi[N]; LL temp; bool fuck[N]; inline void get_primes( int n) //phi数组 { // phi[1] = 1; for ( int i = 2; i <= n; i++) { if (!st[i]) { primes[cnt++] = i; phi[i] = i - 1; } for ( int j = 0; primes[j] * i <= n; j++) { st[primes[j] * i] = true ; if (i % primes[j] == 0) { phi[primes[j] * i] = phi[i] * primes[j]; break ; } phi[primes[j] * i] = phi[i] * (primes[j] - 1); } } } signed main() { //预处理出来了质数数组,然后质数试除 时间复杂度1e5 * ln1e5 互质数直接欧拉函数处理 如果该数为质数便直接不用了 int n; cin>>n; get_primes(n); LL ans = 0; //1LL * n * (n + 1) / 2; for ( register int i = 1; i <= n; i++) //ans加上每个数的互质个数(因为gcd互质数=1) 然后加上每个数的约数之和) { int r = n / i; temp += 1LL * phi[i] * r * (r + 1) / 2; } ans += 2 * temp; ans += 1LL * n * (n + 1) / 2; cout<<ans<<endl; }<br><br><br><br><br> |
作者:@lviy_ptilopsis_
本文为作者原创,转载请注明出处:https://www.cnblogs.com/lviy/p/16210235.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧