洛谷 P4124 CQOI2016 手機號碼

2022-01-10 19:13:06 字數 2990 閱讀 6876

人們選擇手機號碼時都希望號碼好記、吉利。比如號碼中含有幾位相鄰的相同數字、不含諧音不吉利的數字等。手機運營商在發行新號碼時也會考慮這些因素,從號段中選取含有某些特徵的號碼單獨**。為了便於前期規劃,運營商希望開發乙個工具來自動統計號段中滿足特徵的號碼數量。

工具需要檢測的號碼特徵有兩個:號碼中要出現至少 3 個相鄰的相同數字;號碼中不能同時出現 8 和 4。號碼必須同時包含兩個特徵才滿足條件。滿足條件的號碼例如:13000988721、23333333333、14444101000。而不滿足條件的號碼例如:1015400080、10010012022。

手機號碼一定是 11 位數,前不含前導的 0。工具接收兩個數 l* 和 r*,自動統計出 [l,r]區間內所有滿足條件的號碼數量。l 和 r也是 11位的手機號碼。

輸入檔案內容只有一行,為空格分隔的 2 個正整數 l,r。

輸出檔案內容只有一行,為 1 個整數,表示滿足條件的手機號數量。

輸入

12121284000 12121285550
輸出
5
樣例解釋:滿足條件的號碼: 12121285000、 12121285111、 12121285222、 12121285333、 12121285550。

資料範圍:1010

\(\leq\)l\(\leq\)r<1011

一開始我以為這又是一道板子題,只不過狀態有點多,大概要開到6維

於是我就寫了下面的**交了上去

#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

ll f[13][13][13][3][3][3],num[30];

ll a,b;

ll aaaa=0;

ll asd(ll now,ll bef,ll beff,bool jud4,bool jud8,bool jud3,bool lim)

if(f[now][bef][beff][jud4][jud8][jud3]!=-1 && !lim)

ll mmax=9;

if(lim==1) mmax=num[now];

ll anss=0;

for(ll i=0;i<=mmax;i++)

if(!lim) f[now][bef][beff][jud4][jud8][jud3]=anss;

return anss;

}ll solve(ll xx)

return asd(cnt-1,0,0,0,0,0,1);

}int main()

樣例過了,還不錯,於是我就信心滿滿地交了上去,結果發現wa,70分

一開始我認為是字首0的問題,但是一想,其實並沒有那麼簡單,為什麼呢

因為題目中給出的資料範圍是1010

\(\leq\)l\(\leq\)r<1011

也就是說,第一位並不會出現0的情況(我一開始是這麼想的)

即使出現了0,那麼你是把00012345679判成是**號碼還是不是呢,畢竟**號碼和數字不一樣

於是我就檢視了一下wa的資料,發現了乙個神奇的問題

​ wa資料:

輸入:

10000000000 10002098555

答案1685496

使用者輸出

4821665153

輸入:10000000000 23456271996

答案:796184381

使用者輸出

5616164038

輸入:10000000000 53628881996

答案:2186241614

使用者輸出

7006221271

wa的資料竟然都是以10000000000開始的,也就是符合要求的最小的數

這會帶來什麼問題呢?

聰明的你應該已經想到了

我們差分是所傳的引數是solve(bb)-solve(aa-1)

也就是說,如果給出的資料是10000000000的話,我們傳到solve函式中會變成了9999999999,這出現什麼問題呢

這會導致字首0的增多

因為我的函式中傳了當前這一位前面的第一位以及前面的第二位

如果我們是按1010算的話12332112會被算成**號碼,而如果按9*109算的話上面的數就不會被算出**號碼

所以我們只要特判,把1010的結果提前處理就可以了

#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

ll f[13][13][13][3][3][3],num[30];

ll a,b;

ll aaaa=0;

ll asd(ll now,ll bef,ll beff,bool jud4,bool jud8,bool jud3,bool lim)

if(f[now][bef][beff][jud4][jud8][jud3]!=-1 && !lim)

ll mmax=9;

if(lim==1) mmax=num[now];

ll anss=0;

for(ll i=0;i<=mmax;i++)

if(!lim) f[now][bef][beff][jud4][jud8][jud3]=anss;

return anss;

}ll solve(ll xx)

if(yy==9999999999) return 5899826978;

return asd(cnt-1,19,12,0,0,0,1);

}int main()

據說有很多題解過不了10000000000 10000000000這組資料

(應該輸出1)

洛谷P4170 CQOI2007 塗色

假設你有一條長度為5的木版,初始時沒有塗過任何顏色。你希望把它的5個單位長度分別塗上紅 綠 藍 綠 紅色,用乙個長度為5的字串表示這個目標 rgbgr。每次你可以把一段連續的木版塗成乙個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成rrrrr,第二次塗成rgggr,第三次塗成rgbgr,...

洛谷 P4170 CQOI2007 塗色

假設你有一條長度為5的木版,初始時沒有塗過任何顏色。你希望把它的5個單位長度分別塗上紅 綠 藍 綠 紅色,用乙個長度為5的字串表示這個目標 rgbgr。每次你可以把一段連續的木版塗成乙個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成rrrrr,第二次塗成rgggr,第三次塗成rgbgr,...

洛谷 P4170 CQOI2007 塗色

假設你有一條長度為5的木版,初始時沒有塗過任何顏色。你希望把它的5個單位長度分別塗上紅 綠 藍 綠 紅色,用乙個長度為5的字串表示這個目標 rgbgr。每次你可以把一段連續的木版塗成乙個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成rrrrr,第二次塗成rgggr,第三次塗成rgbgr,...