我的PAT系列文章更新重心已移至Github,歡迎來看PAT題解的小伙伴請到Github Pages瀏覽最新內(nèi)容。此處文章目前已更新至與Github Pages同步。歡迎star我的repo。
題目
字符串 APPAPT
中包含了兩個單詞 PAT
,其中第一個 PAT
是第 2 位(P
),第 4 位(A
),第 6 位(T
);第二個
PAT
是第 3 位(P
),第 4 位(A
),第 6 位(T
)。
現(xiàn)給定字符串,問一共可以形成多少個 PAT
?
輸入格式:
輸入只有一行,包含一個字符串,長度不超過 ,只包含
P
、A
、T
三種字母。
輸出格式:
在一行中輸出給定字符串中包含多少個 PAT
。由于結(jié)果可能比較大,只輸出對 1000000007 取余數(shù)的結(jié)果。
輸入樣例:
APPAPT
輸出樣例:
2
思路
這明明是一道數(shù)學(xué)題 。。
怎么分析呢?從前向后掃描:
- 每個A對應(yīng)的PA組合數(shù)量是A之前P的數(shù)量,
- 每個T對應(yīng)的PAT組合數(shù)量是T之前所有A對應(yīng)的PA組合數(shù)量的累加,
- 所有的PAT組合數(shù)量是所有T對應(yīng)的PAT組合數(shù)量的累加
。。。懂?。。。
其實看通過率應(yīng)該是很多人都會的哈。這道題屬于典型的90%時間用于思考,10%時間用于碼代碼的類型。。。。
然后證明一下這個magic number——1000000007為什么是這個數(shù)(大概等于)以及什么時候應(yīng)該取模:
我們用有符號32位整型來計數(shù),按照我代碼里的變量名:P、PA、PAT。
- P每次自增1,因此最大會達(dá)到10^5,不需取模。
- PA每次累加P的值,我們來看一個比較極端的情況:
- "PAPA ... (共50000對PA) ... PA",這樣記錄PA的組合數(shù)量,就是
PA=1 + 2 + 3 + ... + 50000=2500050000,就已經(jīng)大于int了,因此計算PA應(yīng)該取模。 - PAT每次累加PA的值,因此兩個值都會比較大,必須要取模。累加之后(取模之前)的數(shù)會小于2000000013,這個值小于int的最大值2^31-1=2147483647,不會溢出(模取得過大就會在沒來得及取模之前就溢出了,我覺得這是關(guān)鍵)。
- 那用unsigned int呢,PA是不是不需要取模了?我覺得是的。
- 這道題是要檢查答案的,用一個素數(shù)做模應(yīng)該有避免巧合答案的考慮。
寫完這個發(fā)現(xiàn)劉婼的博客 http://www.liuchuo.net/archives/573 也有相關(guān)的解釋,并且解題思路也不一樣,是累加每個A兩邊P和T的個數(shù)之積。
代碼
最新代碼@github,歡迎交流
#include <stdio.h>
#define LIM 1000000007
int main()
{
int P = 0, PA = 0, PAT = 0;
char c;
while((c = getchar()) != '\n')
{
if(c == 'P') P++;
if(c == 'A') PA = (PA + P) % LIM;
if(c == 'T') PAT = (PAT + PA) % LIM;
}
printf("%d", PAT);
return 0;
}