P1310 表示式的值

2022-02-17 16:27:33 字數 3455 閱讀 5612

原題鏈結 

water_lift 一波講解,然後我們就會了這個題,然後我們就要寫部落格啦qwq~

這是個布林表示式基計數問題。

這個其實⊕就是「|」或運算,×就是「&」與運算。

我們將這個式子通俗得看成:x&y 和 x|y

我們設x0是使x為0的方案數,x1是使x為1的方案數;y0是使y為0的方案數,y1是使y為1的方案數;使x&

y'>x&y

為1的方案數?為0的方案數?使x|

y'>x|y

為1的方案數?為0的方案數?

不難發現:

使x&y

'>x&y

為1,那麼x

'>x

和y'>

y都要為1,所以方案數為x1∗

y1'>x1∗y1

使x&y

'>

x&y為0,那麼x

'>x

和y'>y不

都為1,所以方案數為x1∗

y0+x

0∗y1

+x0∗

y0'>x1∗y0+x0∗y1+x0∗y0

使x|y

'>

x|y為1的方案數為x1∗

y1+x

0∗y1

+x1∗

y0'>x1∗y1+x0∗y1+x1∗y0

,為0的方案數為x0∗

y0'>x0∗y0

。x|y'>x1∗

y1+x

0∗y1

+x1∗

y0'>x0∗

y0'>然後我們發現給出的式子乙個特別煩的東東就是:   有括號x|

y'>x1∗

y1+x

0∗y1

+x1∗

y0'>x0∗

y0'>為了去掉括號,我們可以考慮將題目輸入的中綴表示式給它換成字尾表示式(字尾表示式的好處就是式子中沒有括號!)x|

y'>x1∗

y1+x

0∗y1

+x1∗

y0'>x0∗

y0'>腫麼換呢?這確實是乙個難題,還好我們找到了這樣乙個方法(由於太蒟還不會證正確性):

遍歷中綴表示式:

遇到數字,直接放入答案序列

遇到左括號,入棧

遇到右括號,把棧頂到上乙個左括號的元素依次出棧並放入答案序列

遇到乘號,入棧

遇到加號,從棧頂開始彈出這段連續的乘號,並放入答案序列,最後加號入棧

最後把棧裡剩下的元素依次放入答案序列

為什麼是正確的呢?貼一下water_lift的模擬過程(想要更豐富的展現?請看water_lift的部落格):

那麼有了字尾表示式,這麼求值?

遇到數字入棧,遇到運算符號就取出棧頂的兩個元素,將它們進行該運算子的運算後再入棧。

the last question:

題目要求的是使得表示式為0的方案數,那麼在哪填數字?

看一下樣例: 

很顯然就是在這幾個標紅的位置填數字啦:

_+(_*_)

so,我們可以總結一下在**填數字: 式子最前面一定要填個數字(你見哪個式子是符號打頭?),然後「+」和「×」後面要填乙個數字!

到這裡咱們就可以食用**啦:

#include using

namespace

std;

stack

fh; //

中綴表示式轉字尾表示式的時候所要用到的存符號的棧

stack zero; //

乙個存使表示式為0的方案數的棧

stack one; //

乙個存使表示式為1的方案數的棧

string houxu; //

轉化後的字尾表示式

char ch[100001]; //

存輸入的字串

intn,l0,l1,r0,r1;

//這裡l0就是上文的x0,l1是x1,r0是y0,r1是y1

const

int mod=10007

;int

main()

if(ch[i]=='

+') //

如果是'+',要把符號棧棧頂的'*' 都放入字尾表示式的後面

fh.push(ch[i]);

}if(ch[i]=='

)') //

如果是')',則要把'('和')'之間的符號放入字尾表示式的後面

fh.pop();

//彈出左括號

}

if(ch[i]!='

('&&ch[i]!='

)') houxu.push_back('

n'); //

如果不是括號,也就是說如果是'+'或'*',那麼就要在後面填乙個數字

}

while(!fh.empty()) //

將符號棧中剩餘的符號全部放入字尾表示式

for(int i=0;i//

可以看成是字尾表示式求值

else

//如果是符號

else

//|運算 }}

printf("%d

",zero.top()%mod); //

最後剩下的就是使整個表示式為0的方案數

return0;

}

資料結構 P1310 表示式的值

題目鏈結 對於1 位二進位制變數定義兩種運算 運算的優先順序是 先計算括號內的,再計算括號外的。運算優先於 運算,即計算表示式時,先計算 運算,再計算 運算。例如 計算表示式a b c時,先計算 b c,其結果再與 a 做 運算。現給定乙個未完成的表示式,例如 請你在橫線處填入數字00或者11 請問...

洛谷 P1310 表示式的值(棧 DP)

首先因為有優先順序和括號,可以先把表示式化成字尾表示式的形式,其中用 表示這乙個點是數字。用u記錄得到0的方案數,v記錄得到1的方案數。設兩個步驟的運算結果經過每個符號到乙個結果時,第乙個運算結果算出0的方案數為t1,1的方案數為t2。第二個算出0的方案數為t3,算出1的方案數為t4。則有 當符號是...

洛谷 P1310 表示式的值 解題報告

對於1 位二進位制變數定義兩種運算 運算的優先順序是 先計算括號內的,再計算括號外的。運算優先於 運算,即計算表示式時,先計算 運算,再計算 運算。例如 計算表示式a b c時,先計算 b c,其結果再與 a 做 運算。現給定乙個未完成的表示式,例如 請你在橫線處填入數 0或者1 請問有多少種填法可...