题意:有加,乘,次方3种运算,初始值为x,给定运算式,2种操作,第一种:告诉你x的值,求答案模29393。第二种:更改某个位置的运算。
做法:乍一看就像线段树,但是那个操作并不能简单的合并,所以我们得另寻他法。可以发觉29393并不是质数,29393 = 7×13×17×19.
我们对其中因子做线段树,线段树只需要简单的算出对于每个小于质因子的数经过这个区间答案是几即可,最后利用中国剩余定理对答案
进行合并。
AC代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll __int64
#define ull unsigned __int64
#define eps 1e-8
#define NMAX 30000
#define MOD 1000000007
#define lson l,mid,rt<<1,d
#define rson mid+1,r,rt<<1|1,d
#define PI acos(-1)
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
const int maxn = 5e4+10;
int mod[4] = {7,13,17,19};
int quick_mod(int x, int y, int d)
{
int ret = 1, tmp = x;
while(y)
{
if(y&1) ret = ret*tmp%mod[d];
tmp = tmp*tmp%mod[d];
y >>= 1;
}
return ret;
}
struct SegmentTree
{
int num[20];
}T[maxn<<2][4];
int a[maxn][2],ni[4],n;
void pushup(int rt, int d)
{
for(int i = 0; i < mod[d]; i++)
{
int tmp = T[rt<<1][d].num[i];
T[rt][d].num[i] = T[rt<<1|1][d].num[tmp];
}
}
void build(int l, int r, int rt, int d)
{
if(l == r)
{
for(int i = 0; i < mod[d]; i++)
{
if(a[l][1] == 1) T[rt][d].num[i] = (i+a[l][0])%mod[d];
else if(a[l][1] == 2) T[rt][d].num[i] = i*a[l][0]%mod[d];
else if(a[l][1] == 3) T[rt][d].num[i] = quick_mod(i,a[l][0],d);
}
return;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
pushup(rt,d);
}
void update(int L, int k, int op, int l, int r, int rt, int d)
{
if(l == r)
{
for(int i = 0; i < mod[d]; i++)
{
if(op == 1) T[rt][d].num[i] = (i+k)%mod[d];
else if(op == 2) T[rt][d].num[i] = i*k%mod[d];
else if(op == 3) T[rt][d].num[i] = quick_mod(i,k,d);
}
return;
}
int mid = (l+r)>>1;
if(L <= mid) update(L,k,op,lson);
else update(L,k,op,rson);
pushup(rt,d);
}
void upit(int L, int x, int id)
{
update(L,x,id,1,n,1,0);
update(L,x,id,1,n,1,1);
update(L,x,id,1,n,1,2);
update(L,x,id,1,n,1,3);
}
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o.txt","r",stdin);
#endif
ni[0] = quick_mod(13*17*19,5,0);
ni[1] = quick_mod(7*17*19,11,1);
ni[2] = quick_mod(7*13*19,15,2);
ni[3] = quick_mod(7*13*17,17,3);
int t,cas = 1;
scanf("%d",&t);
while(t--)
{
printf("Case #%d:\n",cas++);
int q;
scanf("%d%d",&n,&q);
char s[10];
for(int i = 1; i <= n; i++)
{
scanf("%s",s);
sscanf(s+1,"%d",&a[i][0]);
if(s[0] == '+') a[i][1] = 1;
else if(s[0] == '*') a[i][1] = 2;
else if(s[0] == '^') a[i][1] = 3;
}
build(1,n,1,0);
build(1,n,1,1);
build(1,n,1,2);
build(1,n,1,3);
while(q--)
{
int tmp,x,op;
scanf("%d",&tmp);
if(tmp == 1)
{
scanf("%d",&x);
int t1 = T[1][0].num[x%7], t2 = T[1][1].num[x%13];
int t3 = T[1][2].num[x%17], t4 = T[1][3].num[x%19];
int ans = ni[0]*t1*13*17*19+ni[1]*t2*7*17*19+ni[2]*t3*7*13*19+ni[3]*t4*7*13*17;
printf("%d\n",ans%29393);
}
else
{
int l,x;
scanf("%d",&l);
scanf("%s",s);
sscanf(s+1,"%d",&x);
if(s[0] == '+') upit(l,x,1);
else if(s[0] == '*') upit(l,x,2);
else if(s[0] == '^') upit(l,x,3);
}
}
}
return 0;
}