HNOI2016 大數(number)《莫隊》

2021-07-11 12:57:05 字數 1926 閱讀 6713

一道典型的莫隊。

先預處理出字尾,即f[i]表示i~(n-1) mod p 的值.

但p的值不小,顯然不能直接存,加乙個離散化。

觀察題目,發現一串數s(l~r)整除p滿足s(l~n-1)%p==s(r+1~n-1)%p

但p值為2或5不滿足這個性質需要特判(不過資料中好像沒有,於是筆者沒寫,有興趣的可以自己去寫寫。。。。。。)

然後問題轉化為求一段區間中有幾對相等的f值。

套乙個莫隊。(ans(l,r)可以由【ans(l+1,r),ans(l-1,r),ans(l,r+1),ans(l,r-1)】推出,為保證時間複雜度,用個分塊【因為不會曼哈頓樹】)。

注意:要在數列的後面加乙個f值為0。

#include

#include

#include

#include

#include

#define ll long long

using namespace std;

const int maxn=200000+10;

char a[maxn];

ll p,n,m,s[maxn],_10[maxn]/*_10[i]表示10的i次方modp*/,f[maxn]/*f[i]表示i~l mod p 的值*/,cd[maxn];

ll cur,sum[maxn],kuai,ans[maxn];

struct query

q[maxn];

//把每個區間(l,r)看成乙個點(x,y),相同塊中的點按y排序,否則按x排序,可以保證n^1.5的時間複雜度

bool operator < (const query& a,const query& b)

int main()

char c;

scanf("%s",a);

n=strlen(a);

kuai=(ll)sqrt((double)n);//按x座標分塊,kuai表示沒段塊的長度

cin>>m;

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

scanf("%lld

%lld",&q[i].x,&q[i].y),q[i].x--,q[i].t=i;

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

for(int i=0;is[i]=a[i]-'0';

f[n-1]=s[n-1]%p;

cd[n-1]=f[n-1];

for(int i=n-2;i>=0;i--)

//for(int i=0;iprintf("%lld ",f[i]);printf("\n");

//離散化

cd[n]=0;

sort(cd,cd+n+1);

int tot=0;

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

for(int i=0;iint mid,l=0,r=tot;

while(l>1;

if(cd[mid]1;

else r=mid;

}f[i]=l;

}//**

****

****

****

****

****

****

****

****

****

****

*****

int l,r;

l=1;r=0;

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

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

return

0; }

/*樣例:

1112112131

6151

4*/

題解 HNOI 2016序列

collapse bzoj 這道題在hnoi2016中還算是好的了 這題中如若去掉多組詢問的話可以在o nlogn o n log n 的時間內得解 並查集 但多組詢問必定要優化,發現這種其他結構基本上無法涉足的題目就只能上莫隊了 我也不知道為啥想到莫隊,可能這就是題感吧 減去o nn o n n ...

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 的倍數,那麼...