BZOJ3530 SDOI2014 數數 題解

2022-05-16 12:00:44 字數 1473 閱讀 4470

我們稱乙個正整數n是幸運數,當且僅當它的十進位制表示中不包含數字串集合s中任意乙個元素作為其子串。例如當s=(22,333,0233)時,233是幸運數,2333、20233、3223不是幸運數。

給定n和s,計算不大於n的幸運數個數。

參考:

絕對(對我來說)是道難題,尤其是很久不寫ac自動機與數字dp的我……

首先n特別大,必須得考慮數字dp。

其次給了一堆串,要求不能出現這些串,先建ac自動機再說。

於是得出了乙個愉快的結論:在ac自動機上跑數字dp(寫到這裡我只想用cao來表達我的心情)

設$f[i][j][0/1]$為填到$i$數字,當前在ac自動機的$j$節點處,已經小於等於/大於到$i$位的原數。

此時需要注意:為了方便(因為參考是這麼寫的233),我們正著掃n而非以前的套路倒著掃n,這樣做會帶來一些問題,於是我們將小於等於也拆開,分別用0和1表示。

(ps:那麼反著掃不知道是否可行……以及如果要反著掃的話可能需要反著存串。)

dp式子就不細講了,直接看**理解吧。唯一要注意的是不能有前導0所以第一層我們要特殊處理。

#include#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;const

int p=1e9+7

;const

int l=1505

;struct

actr[l];

char

s[l],s0[l];

int tot,f[l][l][3

];void

insert()

tr[now].ed=1;}

void

getfail()

}while(!q.empty())

else tr[u].a[i]=tr[tr[u].fail].a[i];}}

}inline

int add(int x,int

y)int

main()

getfail();

n=strlen(s0);

int ans=0

;

for(int i=1;i<10;i++)

}for(int i=1;i)

else

if(k==w)

else}}

}for(int i=0;i)

}printf(

"%d\n

",ans);

return0;

}

+

Bzoj 2726 SDOI 任務安排

memory limit 131072kb 64bit io format lld llu description 機器上有n個需要處理的任務,它們構成了乙個序列。這些任務被標號為1到n,因此序列的排列為1,2,3.n。這n個任務被分成若干批,每批包含相鄰的若干任務。從時刻0開始,這些任務被分批加工...

BZOJ3530 數數(AC自動機,動態規劃)

bzoj 很套路的ac 自動機 dp 首先,如果長度小於n 就不存在任何限制 直接大力dp 然後強制限制不能走到帶有標記的點上面 如果長度恰好為 n 的長度 那麼,要考慮是否恰好卡在範圍裡面 於是d p狀態多記一維 表示是否卡在範圍裡面 最後求一下和就行啦 include include inclu...

BZOJ3530 數數(AC自動機,動態規劃)

bzoj 很套路的 ac 自動機 dp 首先,如果長度小於 n 就不存在任何限制 直接大力 dp 然後強制限制不能走到帶有標記的點上面 如果長度恰好為 n 的長度 那麼,要考慮是否恰好卡在範圍裡面 於是 dp 狀態多記一維 表示是否卡在範圍裡面 最後求一下和就行啦 include include i...