hdu5238

题目链接
题意是对于一个数字x,进行一次有n个运算操作的的运算,如*5 +6 ^3,就是对x先*5再+6 再3次幂,然后输出最后的结果对29393取模的答案.
然后接下来有m次操作,有两种,一种是可以把某个运算符修改掉.另一种是把给x赋一个值
直接模拟的话复杂度肯定是受不了的.然后查了题解发现可以和中国剩余定理结合起来,中国剩余定理大概就是,当我们知道一个x对几个互质的pi取模的结果ai,(ai,pi已知)我们可以通过中国剩余定理求出x.
然后我们把29393分解质因数7 13 17 19 ,4个质因数都不是很大,于是我们想到对于给定的x我们先分别对这4个质数取模后经过一系列运算得到的结果再用中国剩余定理合并.
接下来就是修改运算符的,我们考虑用线段树来维护,tree[i][j][rt]存的是x模第i个素数意义下等于j时经过一系列运算后的值,那么tree[i][j][rt] = tree[i][ tree[i][j][rt<<1] ][rt<<1|1] (这个地方不太好理解 , 仔细看看大概也能明白 , 就是j经过左子树的一系列运算后得到的数字再放到右子树里运算后得到的数字 ) 然后修改的时候就是直接单点修改

#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define  LONG long long
const LONG  INF= 0X3f3f3f3f;
const int   MOD=29393;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
#define lson  l , mid , rt<< 1
#define rson  mid + 1 ,r , (rt<<1)+1
#define root 1, m , 1
const int MAXN = 50000+ 50 ;
int mod[5] ;
int tree[4][20][MAXN<<2] ;
int n , m ;
int table [4][20][30000] ;
struct OP
{char c ;int x ;
}num[MAXN];
void Push_Up(int rt)
{for(int i = 0 ; i< 4 ; ++i){for(int j = 0 ; j < mod[i] ; ++j)tree[i][j][rt] = tree[i][ tree[i][j][rt<<1] ][rt<<1|1] ;}
}
int exgcd(int a,int b,int &x,int &y)
{if(b==0){x=1;y=0;return a;}int r=exgcd(b,a%b,x,y);int t=x;x=y;y=t-a/b*y;return r;
}
int CRT(int *a)
{int ans = 0 ;int x , y;for(int i = 0 ;i < 4 ; ++ i){exgcd(MOD /mod[i] ,mod[i] , x , y ) ;;ans = ( ans + a[i] * ( MOD / mod[i] ) *x ) %MOD;}return (ans + MOD)%MOD ;
}
void Build(int l ,int r ,int rt)
{if( l == r ){for(int i = 0 ; i < 4;  ++i){for(int j = 0 ;j < mod[i] ; ++ j)if(num[l].c == '+')tree[i][j][rt] = (j +num[l].x)%mod[i] ;else if(num[l].c == '*')tree[i][j][rt] = (j * num[l].x) % mod[i] ;elsetree[i][j][rt] = (table[i][j][num[l].x]) % mod[i] ;}return ;}int mid = (l + r) /2 ;Build(l , mid , rt<<1) ;Build(mid + 1, r , rt<<1|1 ) ;Push_Up(rt) ;
}
void Update(int rt ,int t)
{for(int i = 0 ; i < 4 ; ++ i){for(int j =0 ; j < mod[i] ; ++j)if(num[t].c == '+')tree[i][j][rt] = (j + num[t].x) % mod[i] ;else if(num[t].c == '*')tree[i][j][rt] = (j * num[t].x) % mod[i] ;elsetree[i][j][rt] = table[i][j][num[t].x] % mod[i] ;}rt >>= 1;while(rt ){Push_Up(rt ) ;rt >>= 1;}
}
int Find(int l ,int r , int rt,int x)
{if(l ==r && l ==x )return rt ;int mid = (l + r) / 2 ;if( x<= mid)return Find(l , mid, rt<<1 , x) ;elsereturn Find(mid+1 , r , rt << 1|1 , x) ;
}
int Q_pow(int a, int b , int c )
{int res = 1;while(b ){if(b&1)res = (res * a) %c ;a = (a *a)%c ;b /= 2 ;}return res%c;
}
int main()
{mod[0] = 7 , mod[1] = 13 , mod[2] = 17 ; mod[3] = 19 ;for(int i = 0 ; i< 4 ; ++ i)for(int j = 0 ; j < mod[i] ; ++j)for(int k = 0 ; k < MOD  ; ++k)table[i][j][k] = Q_pow(j, k,mod[i]) ;int T;cin >>T;int ca= 0 ;while(T -- ){cin >> n >> m;char c ;int x;for(int i = 1 ; i <= n ; ++ i)getchar () ,scanf("%c%d",&num[i].c ,&num[i].x) ;Build(1 , n ,1) ;int op ;int p ;int a[10] ;printf("Case #%d:\n",++ca) ;while(m -- ){scanf("%d",&op) ;if(op == 1){scanf("%d",&x) ;for(int i = 0 ;i < 4; ++i)a[i] =  tree[i][x%mod[i]][1] ;int res = CRT(a);cout<<res<<endl;}else{scanf("%d",&p) ;getchar() ;scanf("%c%d",&c,&x) ;num[p].c = c , num[p].x = x ;int tt = Find(1 , n ,1 , p ) ;Update( tt , p ) ;}}}return 0 ;
}

hdu5238(中国剩余定理+线段树)相关推荐

  1. HDU 5238 Calculator(中国剩余定理+线段树)

    题意: 有加,乘,次方3种运算,初始值为x,给定运算式. 现在有2种操作: 第一种:告诉你x的值,求答案模29393. 第二种:更改某个位置的运算. 解析: 线段树维护值域的问题,但是那个操作并不能简 ...

  2. 【HDU】5238 Calculator 【中国剩余定理+线段树】

    传送门:[HDU]5238 Calculator 题目分析: 模数可以拆成四个小素数:7,13,17,19. 这样我们可以分别对这几个素数跑答案,最后中国剩余定理搞一下就好.中间我们用线段树,保存每个 ...

  3. HDU-5238 Calculator(线段树+中国剩余定理)

    题意 给定一个关于 xxx 的表达式,形如下例: x×4+2^3+8×6" role="presentation" style="position: relat ...

  4. hdu5238 calculator (线段树+crt)

    (并不能)发现29393不是质数,而是等于7*13*17*19 于是可以用四个线段树分别维护模意义下,对x进行一个区间的操作后的值 最后再把这四个的答案用crt拼起来 也可以不crt,而是预处理0~2 ...

  5. 和Leo一起做爱线段树的好孩子HDU5238 Calculator

    额 神仙题 感觉就是一个暴力啊 线段树维护的是一个类似于键值线段树的东西? 每个叶子节点才表示一个操作 而在PushUp的时候合并答案 这个咋合并? 暴力合并.我们记录下当前模意义下所有的答案 然后暴 ...

  6. HDU 5238 Calculator 线段树 中国剩余定理

    题意: 给一个计算器,有一系列计算步骤,只有加,乘,幂三种运算. 有一种查询操作:查询初始值为\(x\)的时候,最终运算结果模\(29393\)的值. 有一种修改操作:可以修改第\(p\)个运算的运算 ...

  7. hdu 5238 Calculator(线段树+CRT)

    题意:有加,乘,次方3种运算,初始值为x,给定运算式,2种操作,第一种:告诉你x的值,求答案模29393.第二种:更改某个位置的运算. 做法:乍一看就像线段树,但是那个操作并不能简单的合并,所以我们得 ...

  8. 中国剩余定理及其代码实现

    初等数论学习计划 中国剩余定理 部分源自于维基百科. 后续会继续补充修改. 初等数论四大定理之一. 1.1 历史背景与特殊情形口诀 中国剩余定理,又称中国余数定理,是数论中的一个关于一元线性同余方程组 ...

  9. 线性同余方程和中国剩余定理学习笔记

    线性同余方程介绍 形如 a x ≡ c ( m o d b ) ax \equiv c \pmod b ax≡c(modb) 的方程被称为 线性同余方程(Congruence Equation). 求 ...

最新文章

  1. Seconds_Behind_Master
  2. 运行webpack-dev-srerver 端口占用错误及解决办法
  3. 如何给 SAP Fiori Elements 应用的字段添加 value help
  4. Docker 从入门到掉坑
  5. 查看回调函数执行在那个线程中的方法
  6. 台湾大学公开课《概率》六到九章笔记以及课程总结
  7. 外媒:特斯拉CEO马斯克加入反对英伟达收购Arm交易行列
  8. python 函数结果缓存一段时间的装饰器
  9. 图像分割方法及性能评价综述
  10. MySQL常用DDL语法总结
  11. StackPanel 控件自动出现滚动条
  12. 原生开发什么意思_原生App是什么意思
  13. SDUT—Python程序设计实验78(函数)
  14. 人生苦短,聊聊Python的那些特点
  15. 笛色青青(2010-11 -07)
  16. iOS多线程编程之NSThread的使用(★★★推荐,为原作者点赞★★★)
  17. 国外开源电子商务平台
  18. STM32使用DMA在Normal模式下二次传输
  19. html如何发送验证码到手机,页面效果,给手机发送验证码
  20. 【学习笔记】docker安装yapi并配置及添加用户、自动同步swagger设置

热门文章

  1. 风火轮树莓派3卡片电脑介绍
  2. 批处理系统,分时系统,分布式系统,多处理/多核处理器系统,集群系统,嵌入式操作系统
  3. 卡路里与脂肪重量的换算
  4. 操作系统【设有一组作业,它们的提交时间及运行时间如下所示:·····················】
  5. 论文阅读笔记:A Two-Step Approach for Event Factuality Identification
  6. Oracle SQL 高版本相关
  7. Spark获取CSV文件导入ClickHouse
  8. UVA11134 传说中的车 Fabled Rooks
  9. 【MicroPython ESP32】手动配网和wifi信息保存示例
  10. wifi android透传源代码,【终极版】ESP8266远程控制wifi透传模块带调试app