BZOJ4542 Hnoi2016 大數 莫隊

2022-05-20 08:17:35 字數 1388 閱讀 2510

小 b 有乙個很大的數 s,長度達到了 n 位;這個數可以看成是乙個串,它可能有前導 0,例如00009312345。小b還有乙個素數p。現在,小 b 提出了 m 個詢問,每個詢問求 s 的乙個子串中有多少子串是 p 的倍數(0 也是p 的倍數)。例如 s為0077時,其子串 007有6個子串:0,0,7,00,07,007;顯然0077的子串007有6個子串都是素數7的倍數。

第一行乙個整數:p。第二行乙個串:s。第三行乙個整數:m。接下來m行,每行兩個整數 fr,to,表示對s 的子串s[fr…to]的一次詢問。注意:s的最左端的數字的位置序號為 1;例如s為213567,則s[1]為 2,s[1…3]為 213。n,m<=100000,p為素數

輸出m行,每行乙個整數,第 i行是第 i個詢問的答案。

11 121121

3 1 6

1 5

1 4 53

2//第乙個詢問問的是整個串,滿足條件的子串分別有:121121,2112,11,121,121。

題解:看到題容易想到用莫隊。用sum[i]表示s的前i位組成的數%p的值,那麼如果i...j能組成乙個%p=0的數,意味著

$sum[j]-sum[i]*10^=0(mod p) \rightarrow sum[j]*10^=sum[i]*10^ (mod p)$

所以離散化一下,然後就變成了問乙個區間中有多少對相同數,的用桶+莫隊即可。

注意特判p=2,p=5的情況!因為上式不再成立!具體方法是直接判斷哪些串的末尾的數能被2和5整除即可。

#include #include #include #include #include using namespace std;

typedef long long ll;

const int maxn=100010;

int b,p,n,m,nm;

char str[maxn];

int v[maxn],s[maxn];

ll sum,ans[maxn];

ll s1[maxn],s2[maxn];

struct node

p[maxn];

struct query

q[maxn];

bool cmpp(node a,node b)

b=int(sqrt(double(n)));

for(i=1;i<=m;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].l--,q[i].org=i;

sort(q+1,q+m+1,cmpq);

l=1,r=0;

for(i=1;i<=m;i++)

for(i=1;i<=m;i++) printf("%lld\n",ans[i]);

return 0;

}

bzoj4542 Hnoi2016 大數 莫隊

小 b 有乙個很大的數 s,長度達到了 n 位 這個數可以看成是乙個串,它可能有前導 0,例如00009312345 小b還有乙個素數p。現在,小 b 提出了 m 個詢問,每個詢問求 s 的乙個子串中有多少子串是 p 的倍數 0 也 是p 的倍數 例如 s為0077時,其子串 007有6個子串 0,...

4542 Hnoi2016 大數 莫隊演算法

555我好弱啊 都說今年的hnoi是無腦資料結構賽,都很好想只是碼 的問題,然而我還是不會做這道題。要退役了啊啊啊。首先我們令si 表示以i 為開頭的字尾形成的數字。對於p 2且p 5的時候,我們可以發現,若存在l,r 滿足sl sr 1 modp 則區間 l r 組成的數字一定是 p 的倍數,那麼...

BZOJ4542 大數, 莫隊

time 2016.09.10 author xiaoyimi 傳送門思路 神奇的東西 斷斷續續地想了一天沒搞出來 因為沒想到離散化 有乙個有趣的性質 定義t i n j is i 10n j 1 mod p s i 是原字串中第i個位置的數字 也就是說123321 在不考慮p的情況下t4 321 ...