觉醒力量 (hidpower)

2019-04-13 22:01发布

觉醒力量 (hidpower)

题目描述

  【题目背景】    从前有一款非常火的游戏被人们称为pokemon,从最初的红绿蓝黄版直到现在的XY版,都受到世界各地小朋友和大朋友们的喜爱。 【题意描述】    作为一名高玩,QQ最近在研究pokemon的觉醒力量。    觉醒力量是一个属性和威力都不确定的神奇技能,它基于pokemon的个体值进行一系列复杂的计算,最后得出属性和威力。由于属性可以扩充打击面,而威力则保证了打击力度,这使得觉醒力量成为一个不可或缺的技能。一只满威力觉醒冰的电龙可以击败草系或地面系的对手,然而在没有觉醒力量的情况下这几乎不可能。    由于不同的怪需要不同属性的觉醒力量,而每种觉醒力量的最大威力又有差别,所以获取觉醒力量的计算公式就显得尤为重要。经过搜集资料,QQ了解了计算公式的以下几个性质:    1、计算公式由恰好n个步骤组成,每个步骤由运算类型和参数组成。    2、运算类型包括加法,减法,乘法和乘方。    3、运算不考虑优先级,输入总是运算的第一参数,而结果代入下一运算步骤。    比如,共计4个运算步骤:+1,*4,-9,^7(这里的^是乘方,不是异或)    如果代入的数据是2,计算过程是:2+1=3,3*4=12,12-9=3,3^7=2187    如果代入的数据是1,计算过程则为:1+1=2,2*4=8,8-9=-1,(-1)^7=-1    觉醒力量的属性决定于最终答案对17的模(若为负数取正模),得数为0~16时分别对应的属性为:    0:Fight     1:Flying 2:Poison 3:Ground 4:Rock    5:Bug    6:Ghost  7:Steel     8:Fire   9:Water    10:Grass    11:Electric 12:Psychic  13:Ice   14:Dragon    15:Dark     16:Fairy    而觉醒力量的威力决定于最终答案对46189的模。(提示,46189^2=2133423721)    所以上述两种情况分别是威力2187的觉醒电和威力46188的觉醒妖(满威力觉醒妖)。    现在,QQ需要通过不断的实践来修正这个计算公式。QQ有一个初始预估的计算公式,每次他会使用公式计算觉醒力量的属性和威力,和实际情况比对,进而修正公式或继续计算。然而,代入如此长的一个公式对于他而言有些吃力,所以他希望你来帮他完成这件事情。    

输入

     第一行,两个数n,m,表示步骤数和操作数。    接下来一行,描述n个步骤,每个步骤由一个运算符和一个参数构成。步骤之间由一个或多个空格分隔。    接下来m行,描述m个操作,有以下两种格式    1 x 其中x是一个整数,表示将x代入公式计算    2 x p 其中x是一个整数,p是一个步骤(格式同上),表示将第x个步骤替换为p    

输出

     对于每个1类型操作,输出一行,表示觉醒力量的属性和威力,空格分隔。    

样例输入

4 5 +1 *4 -9 ^7 1 2 1 1 2 1 -4 1 2 1 1

样例输出

Electric 2187 Fairy 46188 Fight 4403 Rock 5325

提示

  【数据规模和约定】 对于10%的数据,n,m<=5000 另有20%的数据,没有2类操作 对于80%的数据,n,m<=30000 奇数编号测试点没有^操作。 对于100%的数据,n,m<=100000,2操作中1<=x<=n,运算中运算符为+-*^之一,所有其他整数均小于2^31。   solution 先考虑第一问 输入一个数,输出经过运算后%17的结果,支持修改运算符 用线段树维护,另ans[i]表示把i放入(L,R)的结果,i为0~16 tree[k].ans[i]=tree[k*2+1].ans[tree[k*2].ans[i]]; 这样就可以了 第二问可以发现  46189=11*13*17*19 通过构造同余方程可用CRT解出 然而我写了暴力。。 #include #include #include #include #include #include #define maxn 100005 using namespace std; int n,m,Mod[4]={11,13,17,19},t1,t2; struct node{ int v,op; }s[maxn]; char ch[20]; struct no{ int l,r,v[4][20]; }tree[maxn*4]; const char sh[17][10]={ "Fight","Flying","Poison","Ground","Rock","Bug","Ghost","Steel","Fire", "Water","Grass","Electric","Psychic","Ice","Dragon","Dark","Fairy" }; int val(int k,node a,int mod){ long long ans; if(a.op==1)ans=(k+a.v)%mod; if(a.op==2)ans=(k-a.v)%mod; if(a.op==3)ans=(k*(a.v%mod))%mod; if(a.op==4){ long long p=k;ans=1; while(a.v){ if(a.v&1)ans*=p; p*=p;p%=mod;ans%=mod,a.v/=2; } } ans=(ans%mod+mod)%mod; return (int)ans; } void wh(int k){ for(int i=0;i<4;i++){ for(int j=0;j<20;j++) tree[k].v[i][j]=tree[k*2+1].v[i][tree[k*2].v[i][j]]; } } void build(int k,int L,int R){ tree[k].l=L,tree[k].r=R; if(L==R){ for(int i=0;i<4;i++){ for(int j=0;j<20;j++) tree[k].v[i][j]=val(j,s[L],Mod[i]); } return; } int mid=L+R>>1; build(k*2,L,mid);build(k*2+1,mid+1,R); wh(k); } void outp(int k){ int x=tree[1].v[2][k%17]; printf("%s ",sh[x]); int ans[4]; for(int i=0;i<4;i++){ ans[i]=tree[1].v[i][(k%Mod[i])]; } for(int i=ans[3];i<=46188;i+=19){ bool fl=0; for(int j=0;j<3;j++){ if((i%Mod[j])!=ans[j]){ fl=1;break; } } if(!fl){printf("%d ",i);return;} } } node get(){ node fs; scanf(" %s",ch); int len=strlen(ch); if(ch[0]=='+')fs.op=1; if(ch[0]=='-')fs.op=2; if(ch[0]=='*')fs.op=3; if(ch[0]=='^')fs.op=4; int vv=0; for(int j=1;j>1; if(pl<=mid)lian(k*2,pl,a); else lian(k*2+1,pl,a); wh(k); } int main() { cin>>n>>m; for(int i=1;i<=n;i++)s[i]=get(); build(1,1,n); for(int i=1;i<=m;i++){ int t;scanf("%d",&t); if(t==1){ scanf("%d",&t1); outp(t1); } else { int pl;scanf("%d",&pl); node xx; xx=get(); lian(1,pl,xx); } } return 0; }