[acdream_oj1732]求1到n的最小公倍数(n<=1e8)
题意:如标题
思路:如果n在10^6以内则可以用o(nlogn)的暴力,题目给定的是n<=1e8,暴力显然是不行的,考虑到1到n的最小公倍数可以写成2^p1*3^p2*5^p3*...这种素数的幂的乘积形式,对于当前询问n,可知质数x的指数为(int)log(x,n)(因为要满足是公倍数且最小),因为前n个数有n/logn个质数,这样一次处理为o(n/logn*logn) = o(n)的。由于有T组测试数据,直接T次处理肯定会超时,需要离线处理。具体怎么操作呢?首先将T个询问按n从小到大排序,从小到大处理时,每个质数的指数是非递减的,所以只需在上一次的答案上乘以若干质数。如果记录上一个询问后的每个质数的指数,然后遍历所有质数,看质数有没有增加,这样的时间复杂度为o(T*n/logn+n/logn*logn)=o(Tn/logn),跟直接T次在线处理没什么两样,原因是有很多的质数的指数并不会变化,却也被访问了一次。
一种解决办法是预先计算出每个询问n所增加的质数,从小到大枚举每个质数的每个幂,然后在T个询问中二分,得到第一次出现这个幂的n,这样时间复杂度为o(n/logn*logn*logT)=o(nlogT),查询时就相当于是只查了那个最大的n一样,所以查询复杂度为o(n),总复杂度为o(nlogT),虽然过不了此题,但这个思路却可以对付一些其他T比较大,n稍小的数据。
下面讲另一种o(Tsqrt(n)+n)的思路:核心思想是将质数分为两类,一类是小于等于sqrt(n),一类大于sqrt(n),不难发现对于第二类质数,它们的质数要么是1要么是0,也就是说,对于第二类质数,假设它在某个询问n时加进了答案,那么在以后的询问中就不用再考虑了(如果继续加进答案,那么它的指数会超过1),于是不难得到如下算法:对每个询问,枚举第一类质数,判断他们的质数有没有增加(实际操作时用试乘法而不是求一个对数),而第二类质数只需维护当前乘到了哪个质数就行了。下面是代码:
#pragma comment(linker, "/STACK:10240000,10240000") #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <ctime>
#include <cctype>
#include <set>
#include <bitset>
#include <functional>
#include <numeric>
#include <stdexcept>
#include <utility> using namespace std; #define mem0(a) memset(a, 0, sizeof(a))
#define mem_1(a) memset(a, -1, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define define_m int m = (l + r) >> 1
#define rep_up0(a, b) for (int a = 0; a < (b); a++)
#define rep_up1(a, b) for (int a = 1; a <= (b); a++)
#define rep_down0(a, b) for (int a = b - 1; a >= 0; a--)
#define rep_down1(a, b) for (int a = b; a > 0; a--)
#define all(a) (a).begin(), (a).end()
#define lowbit(x) ((x) & (-(x)))
#define constructInt4(name, a, b, c, d) name(int a = 0, int b = 0, int c = 0, int d = 0): a(a), b(b), c(c), d(d) {}
#define constructInt3(name, a, b, c) name(int a = 0, int b = 0, int c = 0): a(a), b(b), c(c) {}
#define constructInt2(name, a, b) name(int a = 0, int b = 0): a(a), b(b) {}
#define pchr(a) putchar(a)
#define pstr(a) printf("%s", a)
#define sstr(a) scanf("%s", a)
#define sint(a) scanf("%d", &a)
#define sint2(a, b) scanf("%d%d", &a, &b)
#define sint3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define pint(a) printf("%d\n", a)
#define test_print1(a) cout << "var1 = " << a << endl
#define test_print2(a, b) cout << "var1 = " << a << ", var2 = " << b << endl
#define test_print3(a, b, c) cout << "var1 = " << a << ", var2 = " << b << ", var3 = " << c << endl
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a) typedef unsigned int uint;
typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi; const int dx[] = {, , -, , , , -, -};
const int dy[] = {-, , , , , -, , - };
const int maxn = 1e8 + ;
const int md = ;
const int inf = 1e9 + ;
const LL inf_L = 1e18 + ;
const double pi = acos(-1.0);
const double eps = 1e-; template<class T>T gcd(T a, T b){return b==?a:gcd(b,a%b);}
template<class T>bool max_update(T &a,const T &b){if(b>a){a = b; return true;}return false;}
template<class T>bool min_update(T &a,const T &b){if(b<a){a = b; return true;}return false;}
template<class T>T condition(bool f, T a, T b){return f?a:b;}
template<class T>void copy_arr(T a[], T b[], int n){rep_up0(i,n)a[i]=b[i];}
int make_id(int x, int y, int n) { return x * n + y; } int vis[];
unsigned int prime[]; int c; void init() {
const int t = 1e8 + ;
for (int i = ; i <= t; i ++) {
int u = i >> , v = i & ;
if (vis[u] & ( << v)) continue;
prime[c ++] = i;
if ((LL)i * i > t) continue;
for (int j = i * i; j <= t; j += i) {
int u = j >> , v = j & ;
vis[u] |= << v;
}
}
} pii node[];
unsigned int out[];
const int max_sq = 1e4;
unsigned int last[]; int main() {
//freopen("in.txt", "r", stdin);
int T, cas;
cin >> T;
cas = T;
init();
while (T --) {
int n;
sint(n);
node[cas - T - ] = make_pair(n, cas - T - );
}
sort(node, node + cas);
unsigned int ans = ;
int n = node[].first;
int cur = ;
for (int i = ; prime[i] < max_sq; i ++) last[i] = ;
rep_up0(i, cas) {
int n = node[i].first;
for (int j = ; prime[j] < max_sq; j ++) {
while ((LL)last[j] * prime[j] <= n) {
last[j] *= prime[j];
ans *= prime[j];
}
}
while (prime[cur] <= n) {
cur ++;
if (prime[cur - ] < max_sq) continue;
ans *= prime[cur - ];
}
out[node[i].second] = ans;
}
rep_up0(i, cas) cout << out[i] << endl;
return ;
}
11巨带我飞 [acdream_oj1732]求1到n的最小公倍数(n<=1e8)的更多相关文章
- 算法 - 求两个自然数的最小公倍数(C++)
//************************************************************************************************** ...
- C# 求俩个正整数的最小公倍数和最大公约数
C# 求俩个正整数的最小公倍数和最大公约数 1.公倍数.最小公倍数 两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数 翻开小学5年级下册PPT 1.1 ...
- 代码代码:输入两个正整数m和n,求其最大公约数和最小公倍数。15 20 5
import java.util.Scanner; //输入两个正整数m和n,求其最大公约数和最小公倍数.15 20 5 public class Test { public static void ...
- Python实现利用最大公约数求三个正整数的最小公倍数示例
Python实现利用最大公约数求三个正整数的最小公倍数示例 本文实例讲述了Python实现利用最大公约数求三个正整数的最小公倍数.分享给大家供大家参考,具体如下: 在求解两个数的小公倍数的方法时,假设 ...
- java求最大公约数,和最小公倍数
import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner sc = ...
- JS求一个数组元素的最小公倍数
求几个数的最小公倍数就是先求出前两个数的最小公倍数,然后再把这个最小公倍数跟第三个数放在一起来求最小公倍数,如此类推... var dbList = []; //两个数的最小公倍数 function ...
- vjudge 最大公约数GCD 直接求最大共约束和最小公倍数的指令
原题链接https://vjudge.net/contest/331993#problem/C 输入2个正整数A,B,求A与B的最大公约数. Input2个数A,B,中间用空格隔开.(1<= A ...
- 辗转相除 求最大公约数!or 最小公倍数
求最大公约数和最小公倍数的经典算法--辗转相除法描述如下: 若要求a,b两数的最大公约数和最小公倍数,令a为a.b中较大数,b为较小数,算法进一步流程: while(b不为0) { temp=a%b: ...
- 输入两个正整数m和n,求其最大公约数和最小公倍数
public static void main(String[] args){ Scanner sc = new Scanner (System.in); int a,b; System.out ...
随机推荐
- Django系列操作
每次用到都去百度找....找的还不行~~得自己改~~耗时耗力虽然不难~~~直接贴代码记录下方便自己用~~~~ Django之分页 定义成一个块,直接引用到对应的位置即可... <div clas ...
- google protobuf c++ 反射
const Descriptor *desc = DescriptorPool::generated_pool()->FindMessageTypeByName(msg_name); asser ...
- 使用 selenium 实现谷歌以图搜图爬虫
使用selenium实现谷歌以图搜图 实现思路 原理非常简单,就是利用selenium去操作浏览器,获取到想要的链接,然后进行图片的下载,和一般的爬虫无异. 用到的技术:multiprocessing ...
- element动态添加表头的正确姿势
1. 第一步循环 el-table-column <el-table-column v-if="item.show" v-for="(item, index) in ...
- 漫谈LiteOS-端云互通组件-MQTT开发指南(上)
1.介绍 SDK简介 Agent Tiny是部署在具备广域网能力.对功耗/存储/计算资源有苛刻限制的终端设备上的轻量级互联互通中间件,您只需调用API接口,便可实现设备快速接入到物联网平台以及数据上报 ...
- sql注入原理+mysql相关知识点
什么是SQL注入 sql就是经常说的数据库,而sql注入就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.SQL注入是比较常见的网络攻击 ...
- 【编程之美】超时重传,滑动窗口,可靠性传输原理C语言实现
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/lihuidashen/p/128003 ...
- Matplotlib 误差线的绘制和子图的创建方式
一.绘制误差线 使用errorbar方法可以绘制误差线. x = np.linspace(0,10,50) dy=0.8 y = np.cos(x) + dy*np.random.randn(50) ...
- php class 访问控制
属性(attribute ) 必须声明访问控制类型 类型: public 公用 protected 受保护的 private 私有的 public 类型的属性 可以在外部访问 protected 及 ...
- 2019-2020-1 20199326《Linux内核原理与分析》第六周作业
本周学习了庖丁解牛Linux内核分析第五章:系统调用的三层机制(下),是上一章的延续 实验内容:使用gdb跟踪分析一个系统调用内核函数 上周实验我选择的getpid这个系统系统调用,这次准备使用gdb ...