HDU 5238 Calculator(中国剩余定理+线段树)
2015-06-17 09:19
337 查看
题意:
有加,乘,次方3种运算,初始值为x,给定运算式。现在有2种操作:
第一种:告诉你x的值,求答案模29393。
第二种:更改某个位置的运算。
解析:
线段树维护值域的问题,但是那个操作并不能简单的合并,因为值域还是很大的数组开不下,所以我们得另寻他法。可以发觉29393并不是质数,29393 = 7×13×17×19。
设:
t1=ans%7t1 = ans\%7,t2=ans%13t2=ans\%13,t3=ans%17t3=ans\%17,t4=ans%19t4=ans\%19
那么问题的解就是模方程组
⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪x≡t1(mod)7x≡t2(mod)13x≡t3(mod)17x≡t4(mod)19\left\{
\begin{aligned}
x≡t1(mod)7 \\
x≡t2(mod)13 \\
x≡t3(mod)17\\
x≡t4(mod)19
\end{aligned}
\right.
所以我们对其中因子做线段树,线段树只需维护对于每个小于质因子的数经过这个区间答案是几即可,最后利用中国剩余定理对答案进行合并。
mymy codecode
[code]#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; }
相关文章推荐
- HBuild+Mui学习笔记(二):一些知识点
- 手机屏幕旋转180度
- SDL音频播放
- JAVA JDK下载以及环境变量设置
- 深度学习笔记8 数据预处理
- 关于设置半透明背景的一些技巧
- 杰西·李佛摩尔的股市存亡战
- C/C++中赋值语句的返回值问题
- vs编写ActiveX控件,无法运行调试配置
- 【j2ee spring】35、巴巴运动网的产品类别管理(2)
- 用ffmpeg把H264数据流解码成YUV420P
- Scala学习(一)--Scala基础学习
- linux定时器
- sdl2.0示例
- Android Loader学习
- android小事记
- Android 4.4 实现状态栏(status bar)透明效果
- 第十四周项目3:OOP版电子词典
- 立方尾不变
- android软重启问题