UVA 1661 Equation

给出一个后缀表达式f(x),最多出现一次x,解方程f(x) = 0。

读取的时候用一个栈保存之前的结点,可以得到一颗二叉树,标记出现‘X‘的路径,先把没有出现‘X‘的子树算完,由于读取建树的时候是由底向上的,

这步可以在读取的时候顺带完成。

注意‘X‘或‘1/x‘在某个结点和‘0‘相乘,那么‘X‘等效与没有出现过,把之后的结点标记为常数。

然后dfs模拟运算和移项。

还有一些输入输出的小细节和几组测试数据,具体看代码。

WA了很多发,去找数据手动对拍好久终于发现(1/(1/x))=0这种情况是被当作无解。。。而我当作x = 0来处理了,QAQ。为何解个一元一次如此艰辛。。。

第一次写5000B+。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 666;
typedef long long ll;

ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; }

struct Fra
{
    ll p,q;
    Fra(ll x = 0,ll y = 1):p(x),q(y){ normal(p,q); }
    void normal(ll &p,ll &q) { ll g = gcd(p,q); p/=g; q/=g; }
    Fra operator = (int x) {  p = x; q = 1; return *this; }
    Fra operator = (ll x) { p = x; q = 1; return *this; }
    Fra operator - () { return {-p,q}; }
    Fra operator + (Fra &r) {
        ll m,n;
        m = p*r.q+r.p*q;
        n = q*r.q;
        normal(m,n);
        return {m,n};
    }
    Fra operator += (Fra& r) { return *this = *this+r; }
    Fra operator - (Fra &r) { return (-r) + *this; }
    Fra operator -= (Fra &r) { return *this = *this-r; }
    Fra operator * (Fra &r) {
        ll m,n;
        m = p*r.p;
        n = q*r.q;
        normal(m,n);
        return {m,n};
    }
    Fra operator *= (Fra &r) { return (*this) = (*this)*r; }
    Fra operator /(Fra &r) { return Fra(r.q,r.p) * (*this); }
    Fra operator /=(Fra &r) { return (*this) = (*this)/r; }
    bool operator == (const Fra& r) const { return p*r.q == r.p*q; }
    bool operator < (Fra& r) { return  p*r.q < r.p*q; }
    void print() { normal(p,q); if(q<0)q = -q,p = -p; printf("%lld/%lld\n",p,q); }
};

struct Node
{
    Node* l,*r;
    Fra f; char op;
    bool fx;
    Node(){};
    Node(Fra &v,Node*a = NULL, Node*b = NULL):f(v),l(a),r(b){};

}nd[maxn];

bool isOp[256];
char rev[256];

Fra cal(Fra &x,Fra &y,char op)
{
    //assert(isOp[op] == true)
    switch(op){
        case ‘+‘:return x+y;
        case ‘-‘: return x-y;
        case ‘*‘: return x*y;
        case ‘/‘: return x/y;
    }
    return {233,1};
}

Fra ans;

void calRev(Fra &x,char op)
{
    switch(op){
        case‘+‘:ans-=x; return;
        case‘*‘:ans/=x; return ;
        case‘-‘:ans = x-ans; return;
        case‘/‘:ans = x/ans; return;
    }
}

//之前要预处理
bool dfs(Node* u)
{
    //*u;
    if(u->l == NULL) return true;
    //assert(u.r)
    if(u->l->fx){
        ans = cal(ans,u->r->f,rev[u->op]); //乘以0的情况已经预处理了
        if(!dfs(u->l)) return false;
    }else if(u->r->fx) {
        calRev(u->l->f,u->op);//移项,ans本身可能会是0
        if(ans.q == 0) { return false; }
        if(!dfs(u->r)) return false;
    }
    return true;
}

Node* read(char ch)
{
    int cnt = 0;
        stack<Node*> stk;
        do{
            while(ch == ‘ ‘)ch = getchar();
            Node &cur = nd[cnt];
            if(isOp[ch]){
                cur.op = ch;
                cur.r = stk.top(); stk.pop();
                cur.l = stk.top(); stk.pop();
                cur.fx = cur.l->fx || cur.r->fx;
                if(cur.fx){ //系数为0的处理
                    if((cur.op == ‘*‘ && (cur.r->fx ? cur.l->f == 0 : cur.r->f == 0))
                    || (cur.op == ‘/‘ && cur.r->fx && cur.l->f == 0) ) {
                        cur.fx = false;
                        cur.f = 0; cur.l = cur.r = NULL;
                    }
                }else { //预处理,边读边算
                    cur.f = cal(cur.l->f,cur.r->f,cur.op);
                    cur.l = cur.r = NULL;
                }
            }else {
                if(ch == ‘X‘){
                    cur.fx = true;
                }else {
                    cur.fx = false;
                    int data = ch-‘0‘;
                    while(ch = getchar(), ch>=‘0‘&&ch<=‘9‘) data = data*10+ch-‘0‘;
                    cur.f = data;
                }
                cur.l = cur.r = NULL;
            }
            stk.push(nd+cnt);
            ch = getchar(); cnt++;
        }while(ch != ‘\n‘&&~ch);
    return stk.top();
}

int main()
{
    //freopen("in.txt","r",stdin);
    isOp[‘+‘] = isOp[‘-‘] = isOp[‘*‘] = isOp[‘/‘] = true;
    rev[‘+‘] = ‘-‘; rev[‘-‘] = ‘+‘; rev[‘*‘] = ‘/‘; rev[‘/‘] = ‘*‘;
    char head;
    while(~(head = getchar())){
        Node* root = read(head);
        if(!root->fx) {
            if(root->f == 0) puts("MULTIPLE");
            else puts("NONE");
            continue;
        }
        ans = 0;
        if(dfs(root)){ printf("X = "); ans.print(); }
        else {puts("NONE"); continue; }
    }
    return 0;
}

/*
1 1 X / /
1 1 X 2 - / /

1 X /
0 X * 1 +
0 X / 1 +

9 9 9 9 9 9 9 9 9 9 9 9 9 X 1 * * * * * * * * * * * * * +
7 6 - 8 / 8 2 * / 0 3 - + 5 5 1 / + 1 X 2 + + 8 8 + + * +
7 8 X + * 1 8 5 7 3 + * * 7 6 6 / 3 + + 6 5 7 / - * / / +
*/
时间: 2024-08-07 00:20:00

UVA 1661 Equation的相关文章

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te

UVA - 12005 Find Solutions (最小因子分解)

Description  Find Solutions  Look at the following equation: c = ab - + 1 Now given the value of c, how many possible values of and a and b are there (a and b must be positive integers)? That is you will have to find the number of pairs (a, b) which

UVA - 10673 - Play with Floor and Ceil (简单数学!)

题目链接:Play with Floor and Ceil UVA - 10673 Play with Floor and Ceil Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu SubmitStatus Description Problem A Play with Floor and Ceil Input: standard input Output: standard output Tim

uva 10428 - The Roots(牛顿迭代法)

题目链接:uva 10428 - The Roots 题目大意:给定一个n次一元多项式,求出所有解. 解题思路:牛顿迭代法,对于任意给定x,通过牛顿迭代法可以趋近距离x最近的解x0.每次找到一个解后,用多项式除法除掉x?x0后继续求解. 牛顿迭代法:xi+1=xi?f(x)f′(x) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn

Carmichael Numbers(Uva 10006)

  Carmichael Numbers An important topic nowadays in computer science is cryptography. Some people even think that cryptography is the only important field in computer science, and that life would not matter at all without cryptography. Alvaro is one

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 11014 - Make a Crystal(容斥原理)

UVA 11014 - Make a Crystal 题目链接 题意:给定一个NxNxN的正方体,求出最多能选几个整数点.使得随意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O).那么全部点就是f(1),之后要去除掉共线的,就是扣掉f(2), f(3), f(5)..f(n).n为素数.由于这些素数中包括了合数的情况,而且这些点必定与f(1)除去这些点以外的点共线,所以扣掉.可是扣掉后会扣掉一些反复的.比方f(6)在f

[UVa] Palindromes(401)

UVA - 401 Palindromes Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description A regular palindrome is a string of numbers or letters that is the same forward as backward. For example, the string "ABCDED

uva 401.Palindromes

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=342 题目意思:给出一段字符串(大写字母+数字组成).判断是否为回文串 or 镜像串 or 回文镜像串 or 什么都不是.每个字母的镜像表格如下 Character Reverse Character Reverse Character Reverse A A M M Y Y B