一、题目

   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. NIST随机数测试软件安装与使用 && igamc:UNDERFLOW

    https://csrc.nist.gov/ https://csrc.nist.gov/projects/random-bit-generation/documentation-and-softwa ...

  2. Leetcode(871)-最低加油次数

    汽车从起点出发驶向目的地,该目的地位于出发位置东面 target 英里处. 沿途有加油站,每个 station[i] 代表一个加油站,它位于出发位置东面 station[i][0] 英里处,并且有 s ...

  3. SQL优化汇总

    今天面某家公司,然后问我SQL优化,感觉有点忘了,今天特此总结一下: 总结得是分两方面:索引优化和查询优化: 一. 索引优化: 1. 独立的列 在进行查询时,索引列不能是表达式的一部分,也不能是函数的 ...

  4. Leetcode(28)-实现strStr()

    实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在,则返 ...

  5. JavaScript预编译过程理解

    1-JavaScript运行三部曲 语法分析 预编译 解释执行 语法分析很简单,就是引擎检查你的代码有没有什么低级的语法错误: 解释执行顾名思义便是执行代码了: 预编译简单理解就是在内存中开辟一些空间 ...

  6. Gym 101128A Promotions(思维 + dfs)题解

    题意:给一有向图,如果A指向B,则A是B的上级.一直i要升职那么他的上级必须都升职.现在给你一个升职人数的区间[a, b],问你升职a人时几个人必被升职,b时几个人必升职,b时几个人没有可能被升职. ...

  7. vue 的 computed 属性在什么时间执行

    vue 的 computed 属性在什么时间执行

  8. 微信公众号代码高亮美化工具 All In One

    微信公众号代码高亮美化工具 All In One markdown 美化 mdnice 编辑器 https://www.mdnice.com/ https://github.com/mdnice ma ...

  9. How to implement an accurate countdown timer with js

    How to implement an accurate countdown timer with js 如何用 js 实现一个精确的倒计时器 原理剖析 web worker js custom ti ...

  10. Redis all in one

    Redis all in one Redis: REmote DIctionary Server https://redis.io/topics/quickstart Download, extrac ...