Light 1289 - LCM from 1 to n (位图标记+素数筛选)
2015-07-16 21:35
453 查看
题目链接:
http://www.lightoj.com/volume_showproblem.php?problem=1289
题目描述:
给出一个n,求出lcm(1,2,3......n)为多少?
解题思路:
lcm(1,2,3,......,n-1,n)等于所有小于n的素数p[i]的max(p[i]^k)相乘。
暴力求解的话,由于时间的限制,很自然的想打了素数线性打标法,但是空间限制无法申请辣么大的标记数组。
这个重要的时刻位图标记就闪亮登场啦!!!!
int可以保存32位二进制,我们就可以把每一位当做一个数,又因为偶数除了二以外都不是素数,所以我们只需要筛选奇数。
http://www.lightoj.com/volume_showproblem.php?problem=1289
题目描述:
给出一个n,求出lcm(1,2,3......n)为多少?
解题思路:
lcm(1,2,3,......,n-1,n)等于所有小于n的素数p[i]的max(p[i]^k)相乘。
暴力求解的话,由于时间的限制,很自然的想打了素数线性打标法,但是空间限制无法申请辣么大的标记数组。
这个重要的时刻位图标记就闪亮登场啦!!!!
int可以保存32位二进制,我们就可以把每一位当做一个数,又因为偶数除了二以外都不是素数,所以我们只需要筛选奇数。
#include <bits/stdc++.h> using namespace std; typedef unsigned int UI; const int maxn = 100000005; const int N = 5800000; UI mul ; int vis[maxn/32+10], p ; int cnt, n; void init () { cnt = 1; p[0] = mul[0] = 2; for (int i=3; i<maxn; i+=2) if (!(vis[i/32]&(1<<((i/2)%16)))) {//寻找代表i的哪一位,偶数不占位数 p[cnt] = i; mul[cnt] = mul[cnt-1] * i; for (int j=3*i; j<maxn; j+=2*i) vis[j/32] |= (1<<((j/2)%16));//删除有因子的位数 cnt ++; } //printf ("%d\n", cnt); } UI solve () { int pos = upper_bound(p, p+cnt, n) - p - 1;//找出最大的比n小的素数 UI ans = mul[pos]; for (int i=0; i<cnt&&p[i]*p[i]<=n; i++) { int tem = p[i]; int tt = p[i] * p[i];//这个tt很有可能溢出int(害的本宝宝wa了好几次) while (tt/tem == p[i] && tt<=n) { tem *= p[i]; tt *= p[i]; } ans *= tem / p[i]; } return ans; } int main () { int t, l = 0; init (); scanf ("%d", &t); while (t --) { scanf ("%d", &n); printf ("Case %d: %u\n", ++l, solve()); } return 0; }
相关文章推荐
- C语言中如何将二维数组作为函数的参数传递
- 多线程编程 基础篇 (一)
- 第十一章:运算符重载,友元函数,重载<<运算符,类的自动转换和强制类型转换
- jfinal 运行机制,我的理解
- DBCP、C3P0、Proxool 、 BoneCP开源连接池的比较
- 通过安装包暗转mysql时,第一次登陆出现 ERROR 1045 (28000): Access denied for user解决方法
- C语言编程基础7.8
- CSU 1160 十进制-十六进制
- 2.Add Two Numbers
- [leetcode] Sort Colors
- IOS--UI--通讯录实战--Plist 取文件
- MySQL 记录的操作
- 获得二叉树中两个节点的所有公共祖先
- Candy
- 程序员对英语的依赖
- pe系统找不到笔记本硬盘怎么办?解决笔记本进入
- 如何获取 Android 设备的CPU核数、时钟频率以及内存大小
- JDBCTemplate---方法介绍和简单示例
- Java并发编程:Callable、Future和FutureTask
- c++ vector push_back 出错或者错误