noip2005等价表达式 ·表达式求值

题目大意

给一个含字母a的表达式,求n个选项中表达式跟一开始那个等价的有哪些

做法

模拟一个多项式显然难以实现
那么我们高兴的找一些素数代入表达式,再随便找一个素数做模
表达式求值优先级表

-()+-*^
(<=<<<<
)
+<>>><<
-<>>><<
*<>>>><
^<>>>>>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
typedef long long LL;
const int Q=10000007;
const int A=33;
LL p[A]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,91,97,131,2930,3033,32767,131071};
int chg[256];
char cmp[7][7]={//前一符号与后一符号比较
    {},
    {' ','<','=','<','<','<','<'},
    {' ',' ',' ',' ',' ',' ',' '},
    {' ','<','>','>','>','<','<'},
    {' ','<','>','>','>','<','<'},
    {' ','<','>','>','>','>','<'},
    {' ','<','>','>','>','>','>'}
};
char t[53],s[53];
int m;
LL ans[A];
LL tmp[A];
int opr[53],stopr;
LL num[A][53];int stnum;

void print(int x)
{
    for(int i=1;i<A;i++) if(tmp[i]!=ans[i]) return;
    printf("%c",'A'+x);
}

LL yusuan(LL a,LL b,int x)
{
    if(x==3) return (a+b)%Q;
    if(x==4) return ((a-b)%Q+Q)%Q;
    if(x==5) return (a*b)%Q;
    if(x==6)
    {
        LL res=1;
        while(b--) res=(res*a)%Q;
        return res;
    }
}

void calc(LL *to)
{
    int n=0,len=strlen(t),i,j,x;LL d;
    for(i=0;i<len;i++) if(t[i]!=' ') s[++n]=t[i];
    stopr=0;stnum=0;
    s[0]='(';s[++n]=')';
    for(i=0;i<=n;i++)
    {
        if(chg[s[i]])
        {
            x=chg[s[i]];
            while(stopr&&cmp[opr[stopr]][x]=='>')
            {
                stnum--;
                for(j=1;j<A;j++) num[j][stnum]=yusuan(num[j][stnum],num[j][stnum+1],opr[stopr]);
                stopr--;
            }
            if(stopr&&cmp[opr[stopr]][x]=='=') stopr--;
            else opr[++stopr]=x;
        }
        else
        {
            if(s[i]=='a')
            {
                ++stnum;
                for(j=1;j<A;j++) num[j][stnum]=p[j]; 
            }
            else
            {
                d=0;
                for(;isdigit(s[i]);i++) d=(d*10+s[i]-'0')%Q;
                i--;
                ++stnum;
                for(j=1;j<A;j++) num[j][stnum]=d; 
            }
        }
    }
    for(i=1;i<A;i++) to[i]=num[i][1];
}

int main()
{
    chg['(']=1;chg[')']=2;
    chg['+']=3;chg['-']=4;
    chg['*']=5;chg['^']=6;
    int i;
    gets(t);
    calc(ans);
    scanf("%d",&m);getchar();
    for(i=0;i<m;i++)
    {
        gets(t);
        calc(tmp);
        print(i);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值