AOJ0264 Finite Field Calculator

問題リンク Finite Field Calculator

  • 解法

構文解析です。
四則演算の解析にちょろっと手を加えれば解けます。

  • ソース
import java.util.Scanner;

//Finite Field Calculator
public class AOJ0264 {

	String s;
	int idx, mod;
	boolean ng;
	
	char get(){
		if(idx==s.length())return '$';
		return s.charAt(idx++);
	}
	
	int[] exgcd(int x, int y){
		int r0 = x, r1 = y, a0 = 1, a1 = 0, b0 = 0, b1 = 1;
		int q1, r2, a2, b2;
		while(0 < r1){
			q1 = r0/r1;
			r2 = r0%r1;
			a2 = a0-q1*a1;
			b2 = b0-q1*b1;
			r0 = r1; r1 = r2;
			a0 = a1; a1 = a2;
			b0 = b1; b1 = b2;
		}
		return new int[]{a0, b0, r0};
	}
	
	int modInverse(int a, int m){
		int[] r = exgcd(a, m);
		return r[2]==1?(m+r[0])%m:-1;
	}
	
	int exp(){
		if(ng)return 0;
		int res = term();
		for(;;){
			char c = get();
			if(c=='+'){
				res += term();
				if(mod <= res)res-=mod;
			}
			else if(c=='-'){
				int ope = term();
				ope = mod-ope;
				res+=ope;
				if(mod <= res)res-=mod;
			}
			else break;
		}
		idx--;
		return res;
	}
	
	int term(){
		if(ng)return 0;
		int res = fact();
		for(;;){
			char c = get();
			if(c=='*'){
				res *= fact();
				res%=mod;
			}
			else if(c=='/'){
				int ope = fact();
				if(ope==0){
					ng = true; return 0;
				}
				ope = modInverse(ope, mod);
				if(ope==-1){
					ng = true; return 0;
				}
				res *= ope;
				res%=mod;
			}
			else break;
		}
		idx--;
		return res;
	}
	
	int fact(){
		if(ng)return 0;
		char c = get();
		if(c=='('){
			int res = exp();
			get();
			return res;
		}
		if(c=='-'){
			int res = exp();
			res%=mod;
			return mod-res;
		}
		int res = c-'0';
		for(;;){
			c = get();
			if(!Character.isDigit(c))break;
			res = res*10 + c-'0';
		}
		idx--;
		return res;
	}
	
	void run(){
		Scanner sc = new Scanner(System.in);
		for(;;){
			String[] t = sc.nextLine().split(":");
			mod = Integer.parseInt(t[0]);
			if(mod==0)break;
			s = t[1].replace(" ", "");
			idx = 0;
			ng = false;
			int res = exp();
			if(ng)System.out.println("NG");
			else System.out.printf("%s = %d (mod %d)\n", s, res, mod);
		}
	}
	
	public static void main(String[] args) {
		new AOJ0264().run();
	}
}