題目描述
description
明明進了中學之後,學到了代數表示式。有一天,他碰到乙個很麻煩的選擇題。這個題目的題幹中首先給出了乙個代數表示式,然後列出了若干選項,每個選項也是乙個代數表示式,題目的要求是判斷選項中哪些代數表示式是和題幹中的表示式等價的。
這個題目手算很麻煩,因為明明對計算機程式設計很感興趣,所以他想是不是可以用計算機來解決這個問題。假設你是明明,能完成這個任務嗎?
這個選擇題中的每個表示式都滿足下面的性質:1.
表示式只可能包含乙個變數『a
』。2.
表示式中出現的數都是正整數,而且都小於
10000。3
.表示式中可以包括四種運算『+
』(加),『-
』(減),『*
』(乘),『^
』(乘冪),以及小括號『(
』,『)
』。小括號的優先順序最高,其次是『^
』,然後是『*
』,最後是『+
』和『-
』。『+
』和『-
』的優先順序是相同的。相同優先順序的運算從左到右進行。(注意:運算子『+
』,『-
』,『*
』,『^
』以及小括號『(
』,『)
』都是英文本元)4.
冪指數只可能是1到
10之間的正整數(包括1和
10)。5.
表示式內部,頭部或者尾部都可能有一些多餘的空格。
下面是一些合理的表示式的例子:
((a^1)
^2)^3
,a*a+a-a
,((a+a))
,9999+(a-a)*a,1
+(a-1)^3
,1^10^9……
輸入描述 input description 輸入
第一行給出的是題幹中的表示式。第二行是乙個整數n(
2<=
n<=
26),表示選項的個數。後面
n行,每行包括乙個選項中的表示式。這
n個選項的標號分別是a,
b,c,
d……輸入中的表示式的長度都不超過
50個字元,而且保證選項中總有表示式和題幹中的表示式是等價的。
輸出描述 output description 輸出
包括一行,這一行包括一系列選項的標號,表示哪些選項是和題幹中的表示式等價的。選項的標號按照字母順序排列,而且之間沒有空格。
樣例輸入 sample input (
a+1)^2
3(a-1)^2+4*aa+
1+aa^2+2*
a*1+
1^2+
10-10
+a-a
樣例輸出 sample output ac
資料範圍及提示 data size & hint
【資料規模】
對於30%
的資料,表示式中只可能出現兩種運算子『+
』和『-
』;對於其它的資料,四種運算子『+
』,『-
』,『*
』,『^
』在表示式中都可能出現。
對於全部的資料,表示式中都可能出現小括號『(
』和『)
』。
此題算是hash演算法的一道基礎題,但是涉及幾個小知識點,所以在此列出。
思路:看到此題首先想到就是表示式求值,但是發現有個變數a,如果我們用乙個常數代替a不就變成表示式求值了,另乙個問題就是求出的答案太大,不易儲存,而且耗費空間不知幾何,按照hash演算法的思想,將表示式的值mod乙個值(素數),這樣計算就簡便很多,問題又來了,我們知道hash是會出現衝突,如果只用一組資料計算那麼衝突的概率就很大,解決這問題就很簡單了,我們多使用幾個常數計算,如果幾個常數求出的答案都一樣我們就直接判定相等的表示式(雖可能還是有衝突,但是概率很小)。
細節:此題的表示式並不一定合法,所以首先需要去掉多餘的空格,把不匹配的括號也去掉,儲存資料注意是否需要用到longlong,算指數時可以考慮使用快速冪,表示式求值使用表示式樹更為簡單一些。
#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;
#define inf 0x3f3f3f3f
#define eps 1e-6
#define clr( a, v ) memset ( a, v, sizeof ( a ) )
#define ll long long
#define dbug printf ( "here!!!\n" )
#define rep( i, a, b ) for ( int i = ( a ); i < ( b ); i ++ )
#define pb push_back
#define ull unsigned long long
#define pi acos ( -1.0 )
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define lowbit( x ) ( ( x )&( -x ) )
#define case int test; scanf ( "%d", &test ); for ( int cas = 1; cas <= test; cas ++ )
#define all( x ) x.begin ( ), x.end ( )
#define ins( x ) inserter ( x, x.begin ( ) )
typedef pair < int, int > pii;
typedef pair < double, double > pdd;
typedef set < int > set;
const int maxn = 105;
int read_int ( )
while ( ch >= '0' && ch <= '9' )
return res*f;
}char str[maxn*maxn], ch[maxn][maxn], res[maxn];
int l[maxn], r[maxn], rt;
bool del[maxn*maxn];
ll ans[5];
ll h[5] = ;
ll mod[5] = ;
void to_space ( char * s )
bool isdigit ( int l, int r, char * s )
int build_tree ( int l, int r, char * s )
int p1, p2, p3, c = 0;
p1 = p2 = p3 = -1;
for ( int i = l; i < r; i ++ )
}if ( p2 == -1 )
p2 = p1;
if ( p3 == -1 )
p3 = p2;
if ( p3 == -1 )
return build_tree ( l+1, r-1, s );
int u = rt ++;
ch[u][0] = s[p3];
ch[u][1] = '\0';
l[u] = build_tree ( l, p3, s );
r[u] = build_tree ( p3+1, r, s );
return u;
}stack < ll > s; //用ll儲存資料
ll toint ( char * s )
ll quick_mod ( ll a, ll b, ll m ) //快速冪
return res;
}ll oper ( ll a, ll b, char c, ll m )
return 0;
}void dfs ( int u, ll x, ll m )
else
}void delbr ( char * s )
int p = 0;
for ( int i = 0; s[i]; i ++ )
if ( del[i] == false )
s[p ++] = s[i];
s[p] = '\0';
c = 0;
clr ( del, false );
for ( int i = p-1; i >= 0; i -- )
p = 0;
for ( int i = 0; s[i]; i ++ )
if ( del[i] == false )
s[p ++] = s[i];
s[p] = '\0';
}void solve ( )
scanf ( "%d", &n );
getchar ( );
int p = 0;
for ( int i = 0; i < n; i ++ )
}//printf ( "\n" );
if ( ok )
res[p ++] = 'a'+i;
}res[p] = '\0';
puts ( res );
}int main ( )
NOIP2005 等價表示式
等價表示式 equal.pas c cpp 問題描述 明明進了中學之後,學到了代數表示式。有一天,他碰到乙個很麻煩的選擇題。這個題目的題幹中首先給出了乙個代數表示式,然後列出了若干選項,每個選項也是乙個代數表示式,題目的要求是判斷選項中哪些代數表示式是和題幹中的表示式等價的。這個題目手算很麻煩,因為...
NOIP 2005 等價表示式
題目描述 明明進了中學之後,學到了代數表示式。有一天,他碰到乙個很麻煩的選擇題。這個題目的題幹中首先給出了乙個代數表示式,然後列出了若干選項,每個選項也是乙個代數表示式,題目的要求是判斷選項中哪些代數表示式是和題幹中的表示式等價的。這個題目手算很麻煩,因為明明對計算機程式設計很感興趣,所以他想是不是...
NOIP2005 等價表示式
明明進了中學之後,學到了代數表示式。有一天,他碰到乙個很麻煩的選擇題。這個題目的題幹中首先給出了乙個代數表示式,然後列出了若干選項,每個選項也是乙個代數表示式,題目的要求是判斷選項中哪些代數表示式是和題幹中的表示式等價的。這個題目手算很麻煩,因為明明對計算機程式設計很感興趣,所以他想是不是可以用計算...