我們稱乙個正整數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...