当前位置: 首页 > 编程日记 > 正文

hdu-3071 Gcd Lcm game---质因数分解+状态压缩+线段树

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3071

题目大意:

给定一个长度为n的序列m次操作,操作的种类一共有三种

    • 查询
      • L :查询一个区间的所有的数的最小公倍数modp
      • G :查询一个区间的所有的数的最大公约数modp
    • 修改
      • C :将给定位置的值修改成x

解题思路:

注意数据范围,每个数字不超过100,所以100以内的质因子最多25个,如果直接求解lcm和gcd的话,long long也是存不下的,所以采用存储质因子的指数,但是如果每个节点存25个值,不仅会超内存,还会超时,所以采用位运算来存每个质因子出现的次数,大于10的质因子最多出现一次,所以只需要1位即可,小于10的有2 3 5 7,2最多出现6次,即2的6次方64,3最多出现4次,5最多出现2次,7最多出现2次

所以用3个bit存2的指数,3个bit存3的指数,2个存5,2个存7,其余的只需要1位

pos数组就存的是这些素数的指数具体存在哪一位

int prime[] = {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[] =   {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};
// 0000 0000 0000 0000 0000 0000 0000 0000
//    |   |  | |
//    2   3  5 7
//用这些位表示各个素数出现的次数

求解gcd和lcm的时候,需要求出不同素因子之间的最大值和最小值,所以需要对2 3 5 7分别求解

其余的由于只有1位可以利用&运算求解,

下面自定义了Min和Max函数,求的就是x和y的gcd和lcm,这里的x和y以及求出的解并不是原来的值,而是存储的是素因子的指数表示的值

//宏定义的x和y的括号不能省略,因为参数可能是一个表达式,需要加上括号
#define _min(x, y) ((x) < (y) ? (x) : (y))//写成宏定义更快
#define _max(x, y) ((x) > (y) ? (x) : (y))
inline int Min(int x, int y)
{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 Max(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));
}

解释一下上面的_min(x&0x70000000, y&0x70000000) 0x70000000 就是16进制的数字,转化成2进制是:

0111 0000 0000 0000 0000 0000 0000 0000

由上面可知第31位到28位存的是2的指数,也就是上面红色部分,用x&0x70000000,就求出了x中2的指数,而且把其他位全部置成0,y也是一样,在其中取出最小值,也就是x和y的gcd中2的指数。

同理求出3 5 7,对于后面的位都是1位,直接用&即可求出最小的指数次数,用 | 求出最大的指数次数。

还需要两个函数,一个是将数字x进行分解,将其变成上述的形式。

一个函数是根据上述形式,求出解并模上p。

inline int turn(int x)//将x质因数分解,并且将指数存在y的每一个bit上
{int y = 0;for(int i = 0; i < 25 && x > 1; i++){int cnt = 0;while(x % prime[i] == 0){x /= prime[i];cnt++;}y |= cnt << pos[i];}return y;
}
inline int back(int x, int p)//将所存的指数转化成原来的数字,并且模上p
{ll y = 1;int k = x >> pos[0];x ^= k << pos[0];//消去2的指数while(k--)y = y * prime[0] % p;k = x >> pos[1];    x ^= k << pos[1];    while(k--)y = y * prime[1] % p;k = x >> pos[2];    x ^= k << pos[2];    while(k--)y = y * prime[2] % p;k = x >> pos[3];    x ^= k << pos[3];    while(k--)y = y * prime[3] % p;for(int i = 4; i < 25; i++)if(x & (1<<pos[i]))y = y * prime[i] % p;return y % p;//此处还要模上p,因为y最开始赋值为1,没有经过while循环的话,就没有模上p,虽然y为1没关系,但是数据中有p=1的时候,此时y没有模上p
}

这两个函数很简单,但是题目很坑,有一个小细节没注意到,WA了一个多小时

就是back函数的最后一句,我本以为每次运算均已经模上了p,后来偷懒就不模上p,但是这导致我一直WA,细想后发现,最开始y = 1,如果进行while里面的乘法的话就会模上p,但是不进行while乘法,就还是原来的1,看了一眼数据范围发现,这个p可以是1,这样的话,答案就是0了,这就是导致WA的原因,为了找错误还写了个生成测试数据的代码

剩下的就是普通的线段树了

这里需要注意的是,这道题时间卡的紧,用内联函数更快,上面的back函数可以优化成下面这个样子,这样会更快。(首先就把2 3 5 7 的i次方算出来,这样可以节省300多ms,因为这几个函数调用太频繁了)

int a[]={1,2,4,8,16,32,64};
int b[]={1,3,9,27,81};
int c[]={1,5,25};
int d[]={1,7,49};
inline int back(int x,int p)
{long long y=1;int k=x>>dpos[0];y=y*a[k]%p;x^=k<<dpos[0];k=x>>dpos[1];y=y*b[k]%p;x^=k<<dpos[1];k=x>>dpos[2];y=y*c[k]%p;x^=k<<dpos[2];k=x>>dpos[3];y=y*d[k]%p;x^=k<<dpos[3];for(int i=4;i<25;i++)if(x&(1<<dpos[i])) y=y*prime[i]%p;return y;
}

Gcd和LCM的查询必须分开写,一开始我只写了一个函数,每次都可以求出两个值,但是一下就超时了。

最后就是这道题的代码啦

  1 #include<bits/stdc++.h>
  2 #define MID(l, r) (l + (r - l) / 2)
  3 #define lson(o) (o<<1)
  4 #define rson(o) (o<<1|1)
  5 #define _min(x, y) ((x) < (y) ? (x) : (y))//写成宏定义更快
  6 #define _max(x, y) ((x) > (y) ? (x) : (y))
  7 using namespace std;
  8 typedef long long ll;
  9 const int maxn = 1e6 + 10;
 10 int prime[] = {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};
 11 int pos[] =   {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};
 12 // 0000 0000 0000 0000 0000 0000 0000 0000
 13 //    |   |  | |
 14 //    2   3  5 7
 15 //用这些位表示各个素数出现的次数
 16 inline int Min(int x, int y)
 17 {
 18     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));
 19 }
 20 inline int Max(int x, int y)
 21 {
 22     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));
 23 }
 24 inline int turn(int x)//将x质因数分解,并且将指数存在y的每一个bit上
 25 {
 26     int y = 0;
 27     for(int i = 0; i < 25 && x > 1; i++)
 28     {
 29         int cnt = 0;
 30         while(x % prime[i] == 0)
 31         {
 32             x /= prime[i];
 33             cnt++;
 34         }
 35         y |= cnt << pos[i];
 36     }
 37     return y;
 38 }
 39 inline int back(int x, int p)//将所存的指数转化成原来的数字,并且模上p
 40 {
 41     ll y = 1;
 42     int k = x >> pos[0];
 43     x ^= k << pos[0];//消去2的指数
 44     while(k--)y = y * prime[0] % p;
 45     k = x >> pos[1];    x ^= k << pos[1];    while(k--)y = y * prime[1] % p;
 46     k = x >> pos[2];    x ^= k << pos[2];    while(k--)y = y * prime[2] % p;
 47     k = x >> pos[3];    x ^= k << pos[3];    while(k--)y = y * prime[3] % p;
 48     for(int i = 4; i < 25; i++)
 49         if(x & (1<<pos[i]))y = y * prime[i] % p;
 50     return y % p;
 51     //此处还要模上p,因为y最开始赋值为1,没有经过while循环的话,就没有模上p,虽然y为1没关系,但是数据中有p=1的时候,此时y没有模上p
 52 }
 53 struct node
 54 {
 55     int l, r;
 56     int gcd, lcm;
 57 }tree[maxn];
 58 int a[maxn];
 59 void build(int o, int l, int r)
 60 {
 61     tree[o].l = l, tree[o].r = r;
 62     if(l == r)
 63     {
 64         tree[o].gcd = tree[o].lcm = turn(a[l]);
 65         return;
 66     }
 67     int m = MID(l ,r), lc = lson(o), rc = rson(o);
 68     build(lc, l, m);
 69     build(rc, m + 1, r);
 70     tree[o].gcd = Min(tree[lc].gcd, tree[rc].gcd);
 71     tree[o].lcm = Max(tree[lc].lcm, tree[rc].lcm);
 72 }
 73 //a[p] = v;
 74 int p, v;
 75 void update(int o)
 76 {
 77     if(tree[o].l == tree[o].r)
 78     {
 79         tree[o].lcm = tree[o].gcd = turn(v);
 80         return;
 81     }
 82     int lc = lson(o), rc = rson(o);
 83     if(p <= tree[lc].r)update(lc);
 84     else update(rc);
 85     tree[o].gcd = Min(tree[lc].gcd, tree[rc].gcd);
 86     tree[o].lcm = Max(tree[lc].lcm, tree[rc].lcm);
 87 }
 88 int Gcd, Lcm;
 89 int ql, qr;
 90 void query_gcd(int o)
 91 {
 92     if(ql <= tree[o].l && qr >= tree[o].r)
 93     {
 94         Gcd = Min(Gcd, tree[o].gcd);
 95         //Lcm = Max(Lcm, tree[o].lcm);
 96         return;
 97     }
 98     int lc = lson(o), rc = rson(o);
 99     if(ql <= tree[lc].r)query_gcd(lc);
100     if(qr >= tree[rc].l)query_gcd(rc);
101 }
102 void query_lcm(int o)
103 {
104     if(ql <= tree[o].l && qr >= tree[o].r)
105     {
106         //Gcd = Min(Gcd, tree[o].gcd);
107         Lcm = Max(Lcm, tree[o].lcm);
108         return;
109     }
110     int lc = lson(o), rc = rson(o);
111     if(ql <= tree[lc].r)query_lcm(lc);
112     if(qr >= tree[rc].l)query_lcm(rc);
113 }
114 int main()
115 {
116     //freopen("output.txt", "w", stdout);
117     int n, q;
118     while(scanf("%d%d", &n, &q) != EOF)
119     {
120         for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
121         build(1, 1, n);
122         char s[5];
123         while(q--)
124         {
125             Gcd = 0x7fffffff;
126             Lcm = 0;
127             scanf("%s", s);
128             if(s[0] == 'C')
129             {
130                 scanf("%d%d", &p, &v);
131                 update(1);
132             }
133             else if(s[0] == 'L')
134             {
135                 scanf("%d%d%d", &ql, &qr, &p);
136                 query_lcm(1);
137                 int ans = back(Lcm, p);
138                 printf("%d\n", ans);
139             }
140             else if(s[0] == 'G')
141             {
142                 scanf("%d%d%d", &ql, &qr, &p);
143                 query_gcd(1);
144                 int ans = back(Gcd, p);
145                 printf("%d\n", ans);
146             }
147         }
148     }
149     return 0;
150 }

转载于:https://www.cnblogs.com/fzl194/p/9034201.html

相关文章:

一个比较保守的404页面

<HTML><HEAD><TITLE>您访问的页面不存在 请转到首页进入</TITLE> <META http-equivContent-Type content"text/html; charsetGB2312"> <META http-equivrefresh content"5;URL /"> <STYLE typetext/css></S…

【组队学习】【34期】组队学习内容详情

第34期 Datawhale 组队学习活动马上就要开始啦&#xff01; 02月09日&#xff08;星期三&#xff09;&#xff0c;宣发&#xff0c;2月组队学习计划&#xff01;。02月12日&#xff08;星期六&#xff09;&#xff0c;进入学习群、开营仪式。 本次组队学习的内容为&#xff1a…

Python组合数据类型之字典类型

单元概述 主要解决问题&#xff1a;让程序更好地处理一组数据 三类重要组合数据类型&#xff1a;集合类型、序列类型和字典类型 学完本章&#xff0c;我们能够在头脑中建立集合、序列和字典的模式来表达对一组数据的表达和处理 1. 定义 首先理解“映射”的概念 -映射是一种键…

maven 插件:Tomcat7

配置 Tocmat 用户 > vim $TOMCAT_PATH%/conf/tomcat-users.xml <tomcat-users><role rolename"manager-gui"/><role rolename"manager-script"/><user username"tomcat" password"linuxmint" roles"mana…

电子学会 软件编程(图形化)二级训练营

电子学会 软件编程&#xff08;图形化&#xff09;二级训练营 试题来源 青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;二级&#xff09;【2019.09】青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;二级&#xff09;【2019…

MacOS无法登录App Store修复

MacOS无法登录App Store修复 2017-03-10 21:13:39 by&#xff1a;SemiconductorKING 先上图&#xff1a; 惨红色的提示信息&#xff0c;把你拒之App Store门外&#xff0c;但是对之放弃、不与之斗争不是我们的节奏&#xff0c;请看破敌攻略&#xff1a; 1.查看你的“关于本机”…

Python文件的使用

本章导言 什么是数据格式化 前言&#xff1a; -学完本章&#xff0c;看待数据会有一种规范/格式化的视角 -方法论:从Python角度理解文件和数据表示 -实践能力:学会编写带有文件输入输出的程序 1. 文件的使用 文件的类型 -文件是数据的抽象和集合&#xff0c;可理解为存储在…

datagridview 点击列标题排序

开发winform中&#xff0c;平时经常用到数据列表&#xff0c;我们大多选用datagridview&#xff0c;但是此控件本身没有排序的功能。参阅网上资料。留下标记&#xff0c;以后备用。 datagridview的数据显示一般是通过数据绑定来实现&#xff0c; 即&#xff1a;this.datagridvi…

围绕圆心形旋转

2019独角兽企业重金招聘Python工程师标准>>> 实现了围绕圆心旋转功能 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Roation : MonoBehaviour {public float range 10;void Update () {float x Mathf.Sin(Mathf.…

【组队学习】【34期】阿里云天池在线编程训练营

阿里云天池在线编程训练营 航路开辟者&#xff1a;陈信达、杨世超、赵子一、马燕鹏领航员&#xff1a;武帅、初晓宇、叶前坤、邱广坤、朱松青航海士&#xff1a;宁彦吉、肖桐、汪超、陈信达、杨世超、赵子一、武帅、初晓宇、叶前坤、邱广坤、朱松青、马燕鹏 基本信息 学习平…

Python一维二维数据的格式化和处理

本章导言 什么是数据格式化 前言&#xff1a; -学完本章&#xff0c;看待数据会有一种规范/格式化的视角 -方法论:从Python角度理解文件和数据表示 -实践能力:学会编写带有文件输入输出的程序 1. 数据组织的维度 维度&#xff1a;一组数据的组织形式-线性还是二维或更高维…

让你的网站提速:图片优化网站推荐

页面的加载时间是每一个设计师都担心的数据&#xff0c;或者至少是每个设计师都应该担心的问题。图片的大小肯定是一个需要留意的问题。这就是为什么在这里写了几个有助于优化页面中的图片的小技巧&#xff0c;这些小技巧将有助于大家解决这个问题&#xff0c;这些小技巧也可以…

JAVA对图片的任意角度旋转,以及镜像操作

package relevantTest;/* * 该代码实现了对图像的水平镜像变换&#xff0c;垂直镜像变换&#xff0c;任意角度旋转&#xff0c;jtf的实时监控&#xff0c;以及对图像的缩放变换&#xff0c;以及按钮的若隐若现效果。 * 在对图像进行任意角度旋转时最好是在原始图片未进行任何操…

【组队学习】【34期】百度飞桨AI达人创造营

百度飞桨AI达人创造营 航路开辟者&#xff1a;百度飞桨领航员&#xff1a;六一航海士&#xff1a;阿水、颜鑫、宋泽山、刘洋、张文恺 基本信息 内容属性&#xff1a;合作课程练习平台&#xff1a;https://aistudio.baidu.com/aistudio/course/introduce/25259?ad-frompdg-1…

安装Python第三方库的三个方法

方法一: (cmd命令行) pip 方法【主要方法&#xff0c;适用于99%的情况】【依赖网络状况】 在命令行输入pip -h 可查看该命令帮助信息 常用pip命令 ① pip install <第三方库名> 安装指定第三方库 参数 -U :update对已经安装的进行版本更新 ② pip uninstall <第三方…

java 基础---继承

继承 一&#xff0c;概述 a) 使用extends关键字可以让一个类继承另一个类&#xff0c;继承的类为子类&#xff0c;被继承的类是父类&#xff0c;子类会自动继承父类的所有方法和属性。 b) 继承使得类和类之间产生了关系 c) 子类可以使用super调用父类成员…

建立CentOS 6.9 的Yum本地源

1、建立一个本地Yum的软件仓库1mkdir /media/cdrom2、把CentOS6.9光盘装载到/media/cdrom1mount /dev/cdrom /media/cdrom3、安装createrepo1 rpm -ivh /media/cdrom/Packages/createrepo-[按tab键] deltarpm-[按tab键] python-deltarpm-[按tab键] createrepo-0.9.9-26.…

【组队学习】【34期】零基础学python编程思维

零基础学python编程思维 航路开辟者&#xff1a;邓林权领航员&#xff1a;沈一航海士&#xff1a;覃嘉俊、马子阳、左凯文 基本信息 开源内容&#xff1a;https://linklearner.com/datawhale-homepage/index.html#/learn/detail/6内容属性&#xff1a;公测课程内容说明&…

Python wordcloud库使用说明

1. 介绍 wordcloud是优秀的词云展示第三方库 -词云以词语为基本单位&#xff0c;更加直观和艺术地展示文本 通过词云&#xff0c;我们可以快速提取大段文本的重要信息 2. 安装 (cmd命令行) pip install wordcloud 3. 使用 w wordcloud.WordCloud()代表一个文本对应的词云…

resin-pro-4.0.34 服務器在windows环境下的配置

resin-pro-4.0.34 服務器在windows环境下的配置(轉載请注明作者:icelong) 到caucho網站上http://www.caucho.com/download/下載resin-pro-4.0.34 Windows下載zip版&#xff0c;Linux下載tgz版 Install JDK 1.4 or later. On Unix, set the JAVA_HOME variable or link /usr/jav…

【组队学习】【34期】Python(一级)

Python&#xff08;一级&#xff09; 航路开辟者&#xff1a;王思齐、马燕鹏领航员&#xff1a;马燕鹏航海士&#xff1a;马燕鹏 基本信息 开源内容&#xff1a;https://github.com/datawhalechina/team-learning-program/tree/master/PythonTest内容属性&#xff1a;公测课…

matlab处理txt文件数据

read_txtfile.,m clear close all clc %load函数一般将用来导入纯数字的文件&#xff0c;可以是文本格式的文件或者是matlab保存的mat格式的文件 positionload(坐标点.txt); %将.txt数据读入到matlab工作空间[m,n]size(position); %获得数据矩阵的大小 j1; sumx0; sumy0; …

Python os库的使用

1. 基本介绍 os提供通用的、基本的操作系统交互功能 os库是Python的标准库&#xff0c;提供几百个处理函数 常用有路径操作、进程管理、环境参数等几类 路径操作&#xff1a;os.path子库&#xff0c;处理文件路径及信息 进程管理&#xff1a;启动系统中其他程序 环境参数&…

(U3D)Time的使用

Time类包含了一个重要的类变量deltaTime&#xff0c;它表示距上一次调用Update或FixedUpdate所用的时间。 因此通过它可以让游戏对象按照一个常速进行旋转&#xff0c;而不是依赖于它的帧频&#xff1a; function Update() { tranform.Rotate(0, 5 * Time.deltaTime, 0); } …

【组队学习】【34期】Scratch(二级)

Scratch&#xff08;二级&#xff09; 航路开辟者&#xff1a;王思齐、马燕鹏领航员&#xff1a;马燕鹏航海士&#xff1a;马燕鹏 基本信息 开源内容&#xff1a;https://github.com/datawhalechina/team-learning-program/tree/master/Scratch内容属性&#xff1a;公测课程…

文件操作示例脚本 tcl

linux 下&#xff0c;经常会对用到文件操作&#xff0c;下面是一个用 tcl 写的文件操作示例脚本&#xff1a; 其中 set f01 [open "fix.tcl" w] 命令表示 打开或者新建一个文件“fix.tcl”&#xff0c;并将其 file ID 设置为 f01&#xff0c;后续就以这个 file ID 来…

Python 第三方库自动安装脚本

需求&#xff1a;批量安装第三方库需要人工干预&#xff0c;能否自动安装&#xff1f; 现假设我们要安装以下库 #BatchInstall.py import os libs {"numpy","matplotlib","pillow","sklearn","requests",\ "jie…

ios 如何改变UISegmentedControl文本的字体大小?

UIFont *Boldfont [UIFont boldSystemFontOfSize:16.0f]; NSDictionary *attributes [NSDictionary dictionaryWithObject:Boldfont forKey:UITextAttributeFont]; [segment setTitleTextAttributes:attributes forState:UIControlStateNormal]; 转载于:https://www.cnblog…

CDN全站加速助力企业云上升级

[2018云栖大会南京分会飞天技术汇专场&#xff0c;阿里巴巴高级技术专家魏晋带来题CDN全站加速助力企业云上升级的演讲。主要内容是结合实际客观案例详细解读全战加速产品如何对动静态业务进行的加速&#xff0c;结合安全WAF等其他运营产品&#xff0c;对如何构建适合大部分业务…

【组队学习】一月微信图文索引

一月微信图文索引 一、组队学习相关 周报&#xff1a; 【新周报&#xff08;049&#xff09;】Datawhale组队学习Datawhale组队学习周报&#xff08;第048周&#xff09;Datawhale组队学习周报&#xff08;第047周&#xff09;Datawhale组队学习周报&#xff08;第046周&…