UVA
来源:互联网 发布:全国地区数据库 编辑:程序博客网 时间:2024/05/29 15:13
UVA - 11426
题意:
求
思路:
因为有两个变的数i,j所以我们考虑固定一个,设为n.那么我们只要分别求出gcd(i,n) == d 的有多少对,那么贡献就是cnt*d.
上面这个和设为f(n) = gcd(1,n)+gcd(2,n) ….+gcd(n-1,n)。
考虑怎么求f(n)。gcd(i,n) = d 可以转化为 gcd(i/d,n/d) = 1。进一步我们可以想到满足gcd(i/d,n/d)=1的对数,就是和n/d互质的数的个数,也就是φ(n/d),所以这一步的贡献就是 d*φ(n/d),f(n)就是要枚举所有n的因子.
得到上面这个东西我们肯定要枚举gcd了,然后利用欧拉筛的方法去预处理k*d,复杂度为调和级数
但是我们这样只是求出每个f(n),那么在设s(n)为我们所要求的和.
s(n) = f(1)+f(2)….f(n) = s(n-1)+f(n). 预处理出所有的f(n)得到所有s(n)即可.
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 5e6+7;vector<int>prime;int phi[maxn];ll f[maxn],s[maxn];int n;void init(){ phi[1] = 1; for(int i = 2;i < maxn;++i) { if(!phi[i]) { prime.push_back(i); phi[i] = i - 1; } for(int j = 0;j < prime.size() && prime[j] * i < maxn;++j) { if(i % prime[j] == 0) { phi[i*prime[j]] = phi[i] * prime[j]; break; } else phi[i*prime[j]] = phi[i]*(prime[j] - 1); } }}void solve(){ memset(f,0,sizeof f); memset(s,0,sizeof s); for(int i = 1;i < maxn;++i) for(int j = i + i;j < maxn; j += i) f[j] += i * phi[j/i]; for(int i = 2;i < maxn;++i) s[i] = s[i-1] + f[i]; return ;}int main(){ init(); solve(); while(~scanf("%d",&n)) { if(n == 0) break; printf("%lld\n",s[n]); } return 0;}
阅读全文
0 0
- uva
- UVA
- UVA
- UVA
- uva
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- console.log()的使用
- pytesseract Windows Error 6错误的解决办法
- 银行储蓄系统的可行性分析
- Linux环境下Python学习(2)
- HDOJ2053_Switch Game
- UVA
- TCP/IP 协议 —— ARP
- java反射(2)获取Class对象的三种方法
- Java并发编程的艺术-第三章之Java内存模型
- Comparable使用在选择排序
- 30天挑战计划
- Android——线程中的通信(一)练习
- 关于className的使用,做一个节日卡切换新人初试。
- linux shell命令中的一些快捷键