2015 上海邀请赛c题 calculator hdu5238
2015-05-29 19:38
351 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5238
题目很不错,注意到29393=7*13*17*19,只要计算出答案模这四个数的值即可通过中国剩余定理解出答案。
那么如何高效求解这四个值呢?
可以用一个映射cha[i][j]表示,i表示mod的值是第i种,j表示对这段区间而言的初始长度。
显然tree[x].cha[j][i]=tree[lr(x)].cha[j][tree[ll(x)].cha[j][i]];
细节都在代码里:
题目很不错,注意到29393=7*13*17*19,只要计算出答案模这四个数的值即可通过中国剩余定理解出答案。
那么如何高效求解这四个值呢?
可以用一个映射cha[i][j]表示,i表示mod的值是第i种,j表示对这段区间而言的初始长度。
显然tree[x].cha[j][i]=tree[lr(x)].cha[j][tree[ll(x)].cha[j][i]];
细节都在代码里:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <cstdlib> #include <vector> #include <set> #include <map> using namespace std; const int mod[4]={7,13,17,19},Mod=29393; //四个mod值 int an[4]; //储存四个分答案 inline int ll(int a) { return 2*a; } inline int lr(int a) { return 2*a+1; } inline int pow (int m,int a,int b) { //对第m个数求模是a^b int ss=1,i=1; while (i<=b) { if(b&i) ss=a*ss%mod[m]; i=i<<1; a=a*a%mod[m]; } return ss; } struct node { int cha[4][19]; }; node tree [200005]; void pushup (int x) { //维护节点x int i,j; for(j=0;j<=3;j++) for(i=0;i<mod[j];i++) tree[x].cha[j][i]=tree[lr(x)].cha[j][tree[ll(x)].cha[j][i]]; } char ope[50005]; //表示初始输入的符号 int val[50005]; //初始数值 void build (int st,int l,int r) { //建树 if(l==r) { int i,j; if(ope[l]=='+') { for(j=0;j<=3;j++) for(i=0;i<mod[j];i++) tree[st].cha[j][i]=(i+val[l])%mod[j]; } else if(ope[l]=='*') { for(j=0;j<=3;j++) for(i=0;i<mod[j];i++) tree[st].cha[j][i]=(i*val[l])%mod[j]; } else if(ope[l]=='^') { for(j=0;j<=3;j++) for(i=0;i<mod[j];i++) tree[st].cha[j][i]=pow(j,i,val[l]); } return ; } int mid=(l+r)/2; build (ll(st),l,mid); build (lr(st),mid+1,r); pushup(st); return ; } void gcd (int a,int b,int &d,int& x,int &y) { //扩展欧几里得 if(!b) { d=a; x=1; y=0; } else { gcd(b,a%b,d,y,x); y-=x*(a/b); } } int get_ans (int ini) { int i,a,w,d,y,x=0; for(i=0;i<=3;i++) { a=ini%mod[i]; an[i]=tree[1].cha[i][a]; // cout<<"ans["<<"i"<<"]:"<<an[i]<<endl; } for(i=0;i<=3;i++) { w=Mod/mod[i]; gcd(mod[i],w,d,d,y); x=(x+y*w*an[i])%Mod; } return (x+Mod)%Mod; } void change (int now,int l,int r,int pos,char oo,int va) { //修改pos位置,now是当前考虑节点的标号,l,r是这个节点的左右界,oo是将要修改为的 int i,j; //符号,va是值 if (l==r) { if(oo=='+') { for(j=0;j<=3;j++) for(i=0;i<mod[j];i++) tree[now].cha[j][i]=(i+va)%mod[j]; } else if(oo=='*') { for(j=0;j<=3;j++) for(i=0;i<mod[j];i++) tree[now].cha[j][i]=(i*va)%mod[j]; } else if(oo=='^') { for(j=0;j<=3;j++) for(i=0;i<mod[j];i++) tree[now].cha[j][i]=pow(j,i,va)%mod[j]; } return ; } int mid=(l+r)/2; if(pos<=mid) change(ll(now),l,mid,pos,oo,va); else change(lr(now),mid+1,r,pos,oo,va); pushup(now); return ; } int main () { // freopen("aa.txt","r",stdin); int T,n,m,cas,i,j,ini,pos,va,ans; char oo; scanf("%d",&T); for(cas=1;cas<=T;cas++) { printf("Case #%d:\n",cas); scanf("%d%d",&n,&m); getchar(); for(i=1;i<=n;i++) { scanf("%c%d",ope+i,val+i); getchar(); } build (1,1,n); for(i=1;i<=m;i++) { scanf("%d",&j); if(j==1) { scanf("%d",&ini); ans=get_ans(ini); printf("%d\n",ans); } else { scanf("%d %c%d",&pos,&oo,&va); change(1,1,n,pos,oo,va); } } } }
相关文章推荐
- 关于matlab中矩阵左除和右除
- Linux信号、信号处理和信号处理函数
- HDU2089(数位DP)
- 人体的五行属性
- 《梦断代码》读书笔记3
- 【8. HA模块】云跳板机服务系统设计及实现
- 【7. 日志分析模块】云跳板机服务系统设计及实现
- 内核中的 platform总线
- 2015.05.29 工作任务与心得
- 【6. 跳板机模块】云跳板机服务系统设计及实现
- MarkDown 分类加载失败
- poj2337 欧拉路径
- hadoop,hbase,hive
- 【5. 监控调度处理模块】云跳板机服务系统设计及实现
- 【4-3 前端模块】云跳板机服务系统设计及实现
- 【4-1 前端模块】跳板机服务系统设计及实现
- python27 in Centos6
- ndroid:使用百度地图SDK定位当前具体位置(类似QQ发表说说的选择地点功能)
- 超市管理系统制定测试计划
- merge sort 一些变种、应用