一、题目

   Gcd & Lcm game

二、分析

  非常好的一题。

  首先考虑比较暴力的做法,肯定要按区间进行处理,对于$lcm$和$gcd$可以用标准的公式进行求,但是求$lcm$的时候是肯定会爆$long long$的。

  考虑用素数分解,将所有的数分解后,发现素因子的个数有限,且每个因子的幂也有限,最多的也就是$2^_6$,然后可以考虑将素因子用二进制的每一位进行表示。对于$2,3,5,7$可能会要的多点,所以多给给几位就可以了,最后发现,刚好可以$32$位以内。

  这里就需要写两个转换函数,然后利用$gcd$和$lcm$的性质进行求解和变换。最后考虑区间查询和单点修改,再用一个线段树即可。  

三、AC代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath> using namespace std;
#define ll long long
#define Min(a,b) ((a)>(b)?(b):(a))
#define Max(a,b) ((a)>(b)?(a):(b))
#define lson (rt<<1)
#define rson (rt<<1|1)
const int MAXN = 1e5;
struct Node
{
int L, G;
}segTree[MAXN<<2];
int Prime[25] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
int Pos[25] = {28,25,23,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}; inline int Gcd(int x, int y)
{
//最后是相&,如果继续用Min,相当于只用了一个导致WA
return Min(x&0x70000000, y&0x70000000) | Min(x&0x0e000000, y&0x0e000000) | Min(x&0x01800000, y&0x01800000) | Min(x&0x00600000, y&0x00600000) | ((x&0x001fffff)&(y&0x001fffff));
}
inline int Lcm(int x, int y)
{
return Max(x&0x70000000, y&0x70000000) | Max(x&0x0e000000, y&0x0e000000) | Max(x&0x01800000, y&0x01800000) | Max(x&0x00600000, y&0x00600000) | ((x&0x001fffff)|(y&0x001fffff));
}
//将x质因素分解,并用二进制表示
inline int Turn(int x)
{
int res, ans = 0;
for(int i = 0; i < 25 && x > 1; i++) {
res = 0;
while(x%Prime[i] == 0) {
res++;
x/=Prime[i];
}
ans |= (res<<Pos[i]);
}
return ans;
} int Mi2[] = {1, 2, 4, 8, 16, 32, 64};
int Mi3[] = {1, 3, 9, 27, 81};
int Mi5[] = {1, 5, 25};
int Mi7[] = {1, 7, 49}; //将二进制表示的数转转换成原来的数并取模
inline int Get(int x, int p)
{
ll ans = 1;
int res = x>>Pos[0];
x ^= res<<Pos[0]; //消去表示2的位上的数
ans = ans*Mi2[res]%p;
//求3的指数并消去
res = x>>Pos[1]; x ^= res<<Pos[1]; ans = ans * Mi3[res] % p;
//求5的指数并消去
res = x>>Pos[2]; x ^= res<<Pos[2]; ans = ans * Mi5[res] % p;
//求7的指数并消去
res = x>>Pos[3]; x ^= res<<Pos[3]; ans = ans * Mi7[res] % p;
for(int i = 4; i < 25; i++) {
if((x>>Pos[i])&1) {
ans = ans * Prime[i] % p;
}
}
return ans % p;
} void Push_up(int rt)
{
segTree[rt].G = Gcd(segTree[lson].G, segTree[rson].G);
segTree[rt].L = Lcm(segTree[lson].L, segTree[rson].L);
return;
} void Build(int rt, int l, int r)
{
if(l == r) {
int a;
scanf("%d", &a);
segTree[rt].G = Turn(a);
segTree[rt].L = Turn(a);
return;
}
int mid = (l + r) >> 1;
Build(lson, l, mid);
Build(rson, mid + 1, r);
Push_up(rt);
} void Change(int rt, int l, int r, int pos, int val)
{
if(l == r) {
segTree[rt].G = Turn(val);
segTree[rt].L = segTree[rt].G;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) {
Change(lson, l, mid, pos, val);
}
else if (pos > mid) {
Change(rson, mid + 1, r, pos, val);
}
Push_up(rt);
} int anslcm, ansgcd;
void Query_lcm(int rt, int l, int r, int L, int R)
{
if(L <= l && r <= R) {
anslcm = Lcm(anslcm, segTree[rt].L);
return;
}
int mid = (l + r) >> 1;
if(L <= mid) {
Query_lcm(lson, l, mid, L, R);
}
if(R > mid) {
Query_lcm(rson, mid + 1, r, L, R);
}
}
void Query_gcd(int rt, int l, int r, int L, int R)
{
if(L <= l && r <= R) {
ansgcd = Gcd(ansgcd, segTree[rt].G);
return;
}
int mid = (l + r) >> 1;
if(L <= mid) {
Query_gcd(lson, l, mid, L, R);
}
if(R > mid) {
Query_gcd(rson, mid + 1, r, L, R);
}
}
int main()
{
//freopen("input.txt", "r", stdin);
int N, Q;
while(scanf("%d%d", &N, &Q) != EOF) {
Build(1, 1, N);
char s[2];
for(int i = 0; i < Q; i++) {
scanf("%s", s);
int a, b, c;
if(s[0] == 'L') {
anslcm = 0;
scanf("%d%d%d", &a, &b, &c);
Query_lcm(1, 1, N, a, b);
int ans = Get(anslcm, c);
printf("%d\n", ans);
}
else if(s[0] == 'G') {
ansgcd = 0x7fffffff;
scanf("%d%d%d", &a, &b, &c);
Query_gcd(1, 1, N, a, b);
int ans = Get(ansgcd, c);
printf("%d\n", ans);
}
else {
scanf("%d%d", &a, &c);
Change(1, 1, N, a, c);
}
}
}
return 0;
}

HDU_3071 Gcd & Lcm game 【素数分解 + 线段树 + 状压】的更多相关文章

  1. Bzoj 3813 奇数国 题解 数论+线段树+状压

    3813: 奇数国 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 748  Solved: 425[Submit][Status][Discuss] ...

  2. hdu 5023 线段树+状压

    http://acm.hdu.edu.cn/showproblem.php?pid=5023 在片段上着色,有两种操作,如下: 第一种:P a b c 把 a 片段至 b 片段的颜色都变为 c . 第 ...

  3. POJ:2777-Count Color(线段树+状压)

    Count Color Time Limit: 1000MS Memory Limit: 65536K Description Chosen Problem Solving and Program d ...

  4. POJ 3468 线段树+状压

    题意:给你n个数,有对区间的加减操作,问某个区间的和是多少. 思路:状压+线段树(要用lazy标记,否则会TLE) //By SiriusRen #include <cstdio> #in ...

  5. poj2777Count Color——线段树+状压

    题目:http://poj.org/problem?id=2777 状压每个颜色的选择情况,取答案时 | 一番: 注意题目中的区间端点可能大小相反,在读入时换一下位置: 注意pushdown()中要l ...

  6. 线段树(压位)luogu P1558色板游戏

    题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, ... L. 现在色板上只 ...

  7. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

  8. zoj3886--Nico Number(素数筛+线段树)

    Nico Number Time Limit: 2 Seconds      Memory Limit: 262144 KB Kousaka Honoka and Minami Kotori are ...

  9. 【HDU5869】 Different GCD Subarray Query 题解 (线段树维护区间GCD)

    题目大意:求区间$[L,R]$中所有子区间产生的最大公因数的个数. ------------------------- 对于$gcd$,我们知道$gcd(a,b,c)=gcd(gcd(a,b),c)$ ...

随机推荐

  1. Linux下为Chromium安装Flash插件

    方案1: http://askubuntu.com/questions/158388/how-do-i-make-chromium-use-flash-from-google-chrome/21647 ...

  2. LaTex公式在线转图片

    Reference https://latex.codecogs.com/gif.latex?THE_FORMULAR 注: 请不要包含空格 或者 将整段url放到浏览器里, 会产生空格等字符的替换, ...

  3. 5分钟学Go 基础01:初识 Go 的第一印象是薪水可观

    本文首发于公众号「5分钟学Go」,一个让你每次花 5 分钟就能掌握一个技能点的公众号.目前在博主连更 5 分钟学Go系列,大家可以关注下,第一时间掌握Go技能.如果想要加群交流,可以在公众号后台回复「 ...

  4. Sentry 中文版

    Sentry 中文版 汉化 https://sentry.io/settings/account/details/ 打开用户设置 User settings 语言选择中文 Simplified Chi ...

  5. 论文 公式 排版 编辑 工具 NoteExpress & MathType

    1 1 论文 公式 排版 编辑 工具: NoteExpress http://www.noteexpress.net/index2.html 1 MathType http://www.dessci. ...

  6. 最新 React 源码学习笔记

    最新 React 源码学习笔记 v17.x.x 框架架构 核心算法 设计模式 编码风格 项目结构 为什么出现 解决了什么问题 有哪些应用场景 refs https://github.com/learn ...

  7. js & Input & Paste & Clipboard & upload & Image

    js & Input & Paste & Clipboard & upload & Image input paste upload image js Clip ...

  8. C-Sharp 调用命令行

    https://stackoverflow.com/questions/1469764/run-command-prompt-commands 带控制台 string strCmdText = &qu ...

  9. 教你玩转CSS 伪元素

    一.CSS 伪元素 CSS伪元素是用来添加一些选择器的特殊效果. 语法 伪元素的语法: selector:pseudo-element {property:value;} CSS类也可以使用伪元素: ...

  10. Java自学第2期——注释、数据类型、运算符、方法

    2.1.注释 注释用于说明某段代码的作用,某个类的用途,某个方法的功能,参数和返回值数据类型的意义等等: 注释非常非常非常重要,回顾代码时通过注释找回思路:团队沟通需要,让别人读懂你的代码,增加效率: ...