HDU 5238 Calculator(中国剩余定理+线段树)
来源:互联网 发布:阿里云com续费 编辑:程序博客网 时间:2024/05/16 08:37
题意:
有加,乘,次方3种运算,初始值为x,给定运算式。
现在有2种操作:
第一种:告诉你x的值,求答案模29393。
第二种:更改某个位置的运算。
解析:
线段树维护值域的问题,但是那个操作并不能简单的合并,因为值域还是很大的数组开不下,所以我们得另寻他法。
可以发觉29393并不是质数,29393 = 7×13×17×19。设:
t1=ans%7 ,t2=ans%13 ,t3=ans%17 ,t4=ans%19 那么问题的解就是模方程组
⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪x≡t1(mod)7x≡t2(mod)13x≡t3(mod)17x≡t4(mod)19 所以我们对其中因子做线段树,线段树只需维护对于每个小于质因子的数经过这个区间答案是几即可,最后利用中国剩余定理对答案进行合并。
#include <cstdio>#include <cstring>#include <algorithm>#define ls (o<<1)#define rs (o<<1|1)using namespace std;const int MAXN = 50005;const int MOD = 29393;int factor[] = {7, 13, 17, 19};//modpow//------------------------------------------int modpow(int a, int k, int p) { int c = 1; while(k) { if(k & 1) c = (c*a) % p; a = (a*a)%p; k >>= 1; } return c;}//segment tree//------------------------------------------struct Oper { char ch; int val; inline void read() { char cmd[10]; scanf("%s", cmd); ch = cmd[0]; sscanf(cmd+1, "%d", &val); } inline int cal(int x, int p) { int ret = 0; switch(ch) { case '+': ret = (x + val) % p; break; case '*': ret = (x * val) % p; break; case '^': ret = modpow(x, val, p); break; } return ret; }} op[MAXN];int pos; //修改的位置struct Tree { int mod; int value[MAXN<<2][20]; inline void pushUp(int o) { //左边维护的值,传到右边维护 for(int i = 0; i < mod; i++) { value[o][i] = value[rs][value[ls][i]]; } } void build(int o, int L, int R) { if(L == R) { for(int i = 0; i < mod; i++) value[o][i] = op[L].cal(i, mod); return ; } int M = (L+R)/2; build(ls, L, M); build(rs, M+1, R); pushUp(o); } void modify(int o, int L, int R) { if(L == R) { for(int i = 0; i < mod; i++) value[o][i] = op[L].cal(i, mod); return ; } int M = (L+R)/2; if(pos <= M) modify(ls, L, M); else modify(rs, M+1, R); pushUp(o); }} tree[4];//------------------------------------------//mod rule//------------------------------------------int exgcd (int a, int b, int &x, int &y) { if ( !b ) { x = 1, y = 0; return a; } int ans = exgcd ( b , a % b , y , x ); y -= a / b * x; return ans;}int calc(int val) { int ans = 0; for (int i = 0 ; i < 4 ; i++) { int tmp = MOD / factor[i] , x , y; exgcd(tmp , factor[i] , x , y); ans = (ans + tree[i].value[1][val % factor[i]] * tmp * (x % factor[i]) ) % MOD ; } return (ans+MOD) % MOD;}//------------------------------------------int n, m;int main() { //freopen("in.txt", "r", stdin); int T, cas = 1; scanf("%d", &T); while(T--) { printf("Case #%d:\n", cas++); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) op[i].read(); for(int i = 0; i < 4; i++) { tree[i].mod = factor[i]; tree[i].build(1, 1, n); } int choice, x; while(m--) { scanf("%d", &choice); if(choice == 1) { scanf("%d", &x); printf("%d\n", calc(x)); }else { scanf("%d", &pos); op[pos].read(); for(int i = 0; i < 4; i++) tree[i].modify(1, 1, n); } } } return 0;}
0 0
- HDU 5238 Calculator(中国剩余定理+线段树)
- HDU 5238 Calculator(线段树+中国剩余定理)
- 【HDU】5238 Calculator 【中国剩余定理+线段树】
- hdu 5238 Calculator(线段树+中国剩余定理)
- hdu - 5238 Calculator(线段树+中国剩余定理)线段树好题
- hdu5238(中国剩余定理+线段树)
- HDU 中国剩余定理
- hdu 1370 中国余数(剩余定理)
- hdu 1370(中国剩余定理)
- hdu 3579(中国剩余定理)
- hdu 1573(中国剩余定理)
- hdu 3579(中国剩余定理非互质)
- HDU 1370 Biorhythms (中国剩余定理)
- hdu 1370 Biorhythms(中国剩余定理)
- hdu 5668 中国剩余定理(模版)
- hdu-5446(中国剩余定理+lucas)
- hdu 5238 Calculator(线段树+CRT)
- hdu-1370(中国剩余定理余数互质)&&hdu-1573(中国剩余定理余数不互质)
- 深度学习笔记8 数据预处理
- Android点击EditText文本框之外任何地方隐藏键盘的解决办法
- vs编写ActiveX控件,无法运行调试配置
- EditText自定义边框背景与动态检测用户输入
- JAVA JDK下载以及环境变量设置
- HDU 5238 Calculator(中国剩余定理+线段树)
- Delphi 各版本下载
- 城市_我们只是过客
- 开始。。。
- 华尔街人必读40本金融佳作
- 手机屏幕旋转180度
- HBuild+Mui学习笔记(二):一些知识点
- 详解Linux中SSH远程访问控制
- 单链表中实现O(1)时间复杂度删除节点