HDU - 5238(剩余定理)

题意:

给出一个计算的序列,包含{+,*,^}三种运算。给出两种操作,1是给出初始值,求按照序列计算的答案,2是修改序列中某个位置的数和运算符。

描述:

问题最后要把结果对29393去模,把模拆分为7*13*17*19,那么如果能够在每次修改后求出

t1 = ans%7; t2=ans%13, t3=ans%17, t4=ans%19.

那么问题的解就是模方程组

『 

 x≡t1(mod)7;

 x≡t2(mod)13;

 x≡t3(mod)17;

 x≡t4(mod)19;

』  

方程组的解。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,n) for(int i=0;i<n;i++)
const int M = 29393;
const int m[] = {7,13,17,19};
const int N = 50505;
int sum[N<<2][4][20],num[N];
char str[N];
int Pow(int x,int y,int dd){
   int a=x,ans=1;
   while(y){
      if(y&1) ans=(ans*a)%dd;
      y>>=1; a=(a*a)%dd;
   }
   return ans;
}
char src[10];
void read(int i){
   scanf("%s",src);
   int len=strlen(src);
   str[i]=src[0];   num[i]=0;
   for(int j=1;j<len;j++) {
      num[i]=num[i]*10+src[j]-'0';
   }
}
int cal(int i,int x,int p){
   if(str[i]=='+') return (x+num[i])%m[p];
   else if(str[i]=='^') return Pow(x,num[i],m[p]);
   return (x*num[i])%m[p];
}
void push_up(int l,int r,int rt,int i){
    rep(j,m[i]) sum[rt][i][j]=sum[rt<<1|1][i][sum[rt<<1][i][j]];
}
void build(int l,int r,int rt,int i){
  if(l==r) {
      rep(j,m[i]) sum[rt][i][j]=cal(l,j,i);
      return ;
  }
  int mid=(l+r)>>1;
  build(lson,i);
  build(rson,i);
  push_up(l,r,rt,i);
}
void update(int l,int r,int rt,int i,int p){
  if(l==r) {
      rep(j,m[i]) sum[rt][i][j]=cal(l,j,i);
      return ;
  }
  int mid=(l+r)>>1;
  if(p<=mid) update(lson,i,p);
  else update(rson,i,p);
  push_up(l,r,rt,i);
}
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 inv(int a,int n){
  int d,x,y;
  gcd(a,n,d,x,y);
  return d==1 ? (x+n)%n:-1;
}
int w[4];
void init(){
   rep(i,4) w[i]=M/m[i];
   rep(i,4) {
     w[i]=w[i]*inv(w[i]%m[i],m[i]);
   }
}
int kase=1,n;
main()
{
    init();
    int T;
    scanf("%d",&T);
    while(T--){
       int Q;
       scanf("%d %d",&n,&Q);
       for(int i=1;i<=n;i++) read(i);
       rep(i,4) {
         build(1,n,1,i);
       }
       printf("Case #%d:\n",kase++);
       while(Q--){
          int cmd,x,y;
          scanf("%d %d",&cmd,&x);
          if(cmd==1){
              int ans=0;
              rep(i,4) ans=(ans+w[i]*sum[1][i][x%m[i]])%M;
              printf("%d\n",ans);
          }
          else{
              read(x);
              rep(i,4) update(1,n,1,i,x);
          }
       }
    }
}


你可能感兴趣的:(HDU - 5238(剩余定理))