非常巧的一个题。
运算过多,肯定得用数据结构维护一些东西,这里要维护的是映射关系,运算的本质其实就是函数,也就是映射。
但是答案对29393取模,对0-29393的数维护映射在空间上和时间上都是撑不住的。
如果仔细观察这个数可以发现,这个数本身不是素数,但是可以分解为4个素数的乘积7*13*17*19。
如果你学过中国剩余定理,就应该知道已知一个数x对m1,m2,m3(这几个数互质)取模的结果a1,a2,a3,就能确定x对m1*m2*m3取模的值是唯一的。
所以我们可以先分别维护出在模四个数下的映射,然后再通过这四个映射下的结果求出对29393取模的结果。
大概就可以了。
#include <bits/stdc++.h>
#define lson o<<1
#define rson o<<1|1
#define MID int mid=(l+r)>>1;
using namespace std;
const int MOD=29393;
const int maxn=50000;
int mm[6]={7,13,17,19};
struct oper
{
char c;
int x;
}op[maxn];
int qmod(int a, int b, int mod)
{
int res=1, base=a;
while(b)
{
if(b&1)res=(res*base)%mod;
b>>=1;
base=(base*base)%mod;
}
return res;
}
struct sgtree
{
int n, mod;
struct node
{
int mp[22];
}val[maxn<<2];
void init(int x){ n=mod=x;}
void mapping(int o, int id)
{
int i, x=op[id].x;
if(op[id].c=='+')
{
for(i=0; i<n; i++)
{
val[o].mp[i]=(i+x)%mod;
}
}
else if(op[id].c=='*')
{
for(i=0; i<n; i++)
{
val[o].mp[i]=(i*x)%mod;
}
}
else
{
for(i=0; i<n; i++)
{
val[o].mp[i]=qmod(i, x, mod);
}
}
return;
}
void merg(int o)
{
for(int i=0; i<n; i++)
{
val[o].mp[i]=val[rson].mp[val[lson].mp[i]];
}
return;
}
void build(int o, int l, int r)
{
if(l==r)
{
mapping(o, l);
// for(int i=0; i<n; i++)printf("%d ", val[o].mp[i]);printf("l%d r%d\n", l, r);
return;
}
MID
build(lson, l, mid);
build(rson, mid+1, r);
merg(o);
// for(int i=0; i<n; i++)printf("%d ", val[o].mp[i]);printf("l%d r%d\n", l, r);
return;
}
void update(int o, int l, int r, int x)
{
if(l==r && l==x)
{
mapping(o, x);
return;
}
MID
if(x<=mid)update(lson, l, mid, x);
if(mid<x)update(rson, mid+1, r, x);
merg(o);
return;
}
}sg[5];
int query(int x)
{
int i, m1, m2, ans=0;
for(i=0; i<4; i++)
{
m1=29393/sg[i].n;
ans=(ans+m1*qmod(m1, sg[i].mod-2, sg[i].mod)*sg[i].val[1].mp[x%sg[i].n])%MOD;
}
return ans%MOD;
}
void change(int id, char *a)
{
int i;
op[id].c=a[0], op[id].x=0;
for(i=1; a[i]; i++)
{
op[id].x=op[id].x*10+a[i]-'0';
}
return;
}
char a[20];
int main()
{
int n, m, t, i, j, e=1;
cin>>t;
while(t--)
{
scanf("%d%d", &n, &m);
for(i=1; i<=n; i++)
{
scanf("%s", a);
change(i, a);
}
int x, y;
for(i=0; i<4; i++)
{
sg[i].init(mm[i]);
sg[i].build(1, 1, n);
// for(int j=0; j<mm[i]; j++)printf("%d ", sg[i].val[1].mp[j]);printf("\n");
}
printf("Case #%d:\n", e++);
for(i=1; i<=m; i++)
{
scanf("%d%d", &x, &y);
if(x==1)printf("%d\n", query(y));
else
{
scanf("%s", a);
change(y, a);
for(int i=0; i<4; i++)sg[i].update(1, 1, n, y);
}
}
}
}