SPOJ - VLATTICE Visible Lattice Points(gcd(x,y,z)=1的对数/莫比乌斯反演)
2016-06-04 13:57
411 查看
题目链接:
SPOJ - VLATTICE Visible Lattice Points
题意:
一个n*n*n的方格,从最左下角(0, 0, 0)最多可以看到多少个点?(不被遮挡)包括方格内部。
分析:
假设能看到的点的坐标为(x,y,z)则必须满足:gcd(x,y,z)=1。(0≤x,y,z≤n)。
当x=y=z=0时是不成立的。
当x,y,z中有两个为0时,只有三种情况(0,0,1),(0,1,0),(1,0,0).
当x,y,z中有一个为0时,相当于求gcd(x,y)=1(1≤x,y≤n)的对数。
当x,y,z均大于0时,相当于求gcd(x,y,z)=1(1≤x,y,z≤n)的对数。
对于后两种情况用莫比乌斯反演解决。别忘了倒数第二种情况需要乘以3,因为1的位置有三种。
SPOJ - VLATTICE Visible Lattice Points
题意:
一个n*n*n的方格,从最左下角(0, 0, 0)最多可以看到多少个点?(不被遮挡)包括方格内部。
分析:
假设能看到的点的坐标为(x,y,z)则必须满足:gcd(x,y,z)=1。(0≤x,y,z≤n)。
当x=y=z=0时是不成立的。
当x,y,z中有两个为0时,只有三种情况(0,0,1),(0,1,0),(1,0,0).
当x,y,z中有一个为0时,相当于求gcd(x,y)=1(1≤x,y≤n)的对数。
当x,y,z均大于0时,相当于求gcd(x,y,z)=1(1≤x,y,z≤n)的对数。
对于后两种情况用莫比乌斯反演解决。别忘了倒数第二种情况需要乘以3,因为1的位置有三种。
#include <cstdio> #include <cstring> #include <string> #include <cmath> #include <algorithm> #include <bitset> using namespace std; typedef long long ll; const int MAX_N = 1000010; int prime_cnt; int prime[MAX_N], mu[MAX_N], sum[MAX_N]; bitset<MAX_N> bs; void GetMu() { bs.set(); prime_cnt = 0; mu[1] = 1; for(int i = 2; i < MAX_N; ++i ) { if(bs[i] == 1) { prime[prime_cnt++] = i; mu[i] = -1; } for(int j = 0; j < prime_cnt && i * prime[j] < MAX_N; ++j ){ bs[i * prime[j]] = 0; if(i % prime[j]) { mu[i * prime[j]] = -mu[i]; }else { mu[i * prime[j]] = 0; break; } } } for(int i = 1; i < MAX_N; i++) { sum[i] = sum[i - 1] + mu[i]; } } ll solve(int n) { int last; ll ans = 3; //当有两个数是0时,有3种情况 for(int i = 1; i <= n; ++i) { last = n / (n / i); ll tmp =(ll)(n / i); //当x, y, z均大于0时 ans += tmp * tmp * tmp * (sum[last] - sum[i - 1]); //当有1个数为0时,相当于gcd(x, y) = 1的对数,但是考虑0的位置有3种,所以要乘上3 ans += tmp * tmp * (sum[last] - sum[i - 1]) * 3; i = last; } return ans; } int main() { GetMu(); int T, n; scanf("%d", &T); while(T--){ scanf("%d", &n); printf("%lld\n", solve(n)); } return 0; }
相关文章推荐
- 1.m分解阶乘之和
- 2.几种递推数
- 3.欧拉函数
- 4.快速幂模m算法
- 5.扩展欧几里得&&中国剩余定理
- 6.数论_web
- Project Euler Problem 387 - Harshad Numbers - 深度优先
- 编程之美2015初赛A
- 数论题集
- 原根
- 阶与原根学习笔记
- HDU 1299 Diophantus of Alexandria
- Leftmost Digit(HDU 1060)
- Rightmost Digit(HDU 1061)
- Python-在奇数中寻找素数
- ZOJ 2674 Strange Limit 欧拉定理
- LeetCode-Palindrome Number
- 组合数求模总结
- Sicily 1047 Super Snooker
- 【数论】组合数求模