zoukankan      html  css  js  c++  java
  • 觉醒力量 (hidpower)

    觉醒力量 (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<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #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<len;j++)vv=vv*10+ch[j]-'0';
        fs.v=vv;
        return fs;
    }
    void lian(int k,int pl,node a){
        if(tree[k].l==tree[k].r){
            for(int i=0;i<4;i++){
                for(int j=0;j<20;j++)
                tree[k].v[i][j]=val(j,a,Mod[i]);
            }
            return;
        }
        int mid=tree[k].l+tree[k].r>>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;
    }

     

  • 相关阅读:
    设计模式详解(一):单例模式
    6大设计原则详解(二)
    6大设计原则详解(一)
    Java线程池的创建详解
    Jquery实现表单动态加减、ajax表单提交
    Java并发编程:浅析几种线程安全模型 [转]
    Java并发之线程状态及Thread常用方法
    Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore[转]
    Java并发之synchronized使用
    Java分布式锁之数据库方式实现
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358883.html
Copyright © 2011-2022 走看看