小 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 ...