hdu5238 calculator (线段树+crt)

(并不能)发现29393不是质数,而是等于7*13*17*19

于是可以用四个线段树分别维护模意义下,对x进行一个区间的操作后的值

最后再把这四个的答案用crt拼起来

也可以不crt,而是预处理0~29392的每个情况

为了降低复杂度,预处理模7/13/17/19的幂

注意询问时,要把询问对7/13/17/19先取模

复杂度$O((7+13+17+19)nlogn)$

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define pa pair<int,int>
  5 #define CLR(a,x) memset(a,x,sizeof(a))
  6 using namespace std;
  7 const int maxn=5e4+10;
  8 
  9 inline int rd(){
 10     int x=0;char c=getchar();int neg=1;
 11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 12     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 13     return x*neg;
 14 }
 15 
 16 struct Node{
 17     int op,v;
 18 };
 19 
 20 int Pow[20][20][20],ans[10][15][20][20];
 21 
 22 inline void init_pow(int x){
 23     for(int i=0;i<x;i++){
 24         Pow[x][i][0]=1;
 25         for(int j=1;j<x-1;j++) Pow[x][i][j]=Pow[x][i][j-1]*i%x;
 26     }
 27 }
 28 
 29 inline int fpow(int x,int y,int mod){
 30     return Pow[mod][x%mod][y%(mod-1)];
 31 }
 32 
 33 inline int cal(int x,Node y,int mod){
 34     if(y.op==1) return (x+y.v)%mod;
 35     else if(y.op==2) return x*y.v%mod;
 36     else return fpow(x,y.v,mod);
 37 }
 38 
 39 struct SegT{
 40     int trans[maxn<<2][20],mod;
 41     
 42     inline void update(int p){
 43         int a=p<<1,b=p<<1|1;
 44         for(int i=0;i<mod;i++){
 45             trans[p][i]=trans[b][trans[a][i]];
 46         }
 47     }
 48     inline void change(int p,int l,int r,int x,Node y){
 49         if(l==r){
 50             for(int i=0;i<mod;i++) trans[p][i]=cal(i,y,mod);
 51         }else{
 52             int m=(l+r)>>1;
 53             if(x<=m) change(p<<1,l,m,x,y);
 54             else change(p<<1|1,m+1,r,x,y);
 55             update(p);
 56         }
 57     }
 58 }tr[4];
 59 
 60 int N,M;
 61 
 62 inline Node getnode(){
 63     char s[10];Node x;
 64     scanf("%s",s);
 65     if(s[0]=='+') x.op=1;
 66     else if(s[0]=='*') x.op=2;
 67     else x.op=3;
 68     x.v=0;
 69     for(int k=1,j=strlen(s);k<j;k++) x.v=x.v*10+s[k]-'0';
 70     return x;
 71 }
 72 
 73 inline int solve(int x){
 74     int a[5];
 75     for(int i=0;i<4;i++) a[i]=tr[i].trans[1][x%tr[i].mod];
 76     return ans[a[0]][a[1]][a[2]][a[3]];
 77 }
 78 
 79 int main(){
 80     int i,j,k;
 81     tr[0].mod=7,tr[1].mod=13,tr[2].mod=17,tr[3].mod=19;
 82     init_pow(7),init_pow(13),init_pow(17),init_pow(19);
 83     for(i=0;i<29393;i++){
 84         ans[i%7][i%13][i%17][i%19]=i;
 85     }
 86     for(int T=rd(),t=1;t<=T;t++){
 87         for(i=0;i<4;i++){
 88             for(j=1;j<=4*N;j++){
 89                 for(k=0;k<tr[i].mod;k++)
 90                     tr[i].trans[j][k]=k;
 91             }
 92         }
 93         printf("Case #%d:\n",t);
 94         N=rd(),M=rd();
 95         for(i=1;i<=N;i++){
 96             Node x=getnode();
 97             for(j=0;j<4;j++) tr[j].change(1,1,N,i,x);
 98         }
 99         for(i=1;i<=M;i++){
100             int a=rd();
101             if(a==1){
102                 printf("%d\n",solve(rd()));
103             }else{
104                 int x=rd();Node y=getnode();
105                 for(j=0;j<4;j++) tr[j].change(1,1,N,x,y);
106             }
107         }
108     }
109     return 0;
110 }

 

posted @ 2018-12-08 21:42  Ressed  阅读(218)  评论(0编辑  收藏  举报