【BZOJ4542】大数, 莫队

来源:互联网 发布:郭天祥十天单片机pdf 编辑:程序博客网 时间:2024/06/05 03:21

Time:2016.09.10
Author:xiaoyimi
转载注明出处谢谢


传送门
思路:
神奇的东西
断断续续地想了一天没搞出来
因为没想到离散化(╯‵□′)╯︵┻━┻
有一个有趣的性质
定义Ti=nj=is[i]10nj+1 (mod P)
s[i]是原字符串中第i个位置的数字
也就是说123321
在不考虑P的情况下T4=321,T1=123321
如果存在x,y(x<y)
Tx=Ty且P!=2,P!=5
那么s[x..y]就是一个合法解
TxTy=s[x..y]10ny
P是非2非5的质数
那么s[x..y]这个数一定包含质因子P
然后就可以直接莫队,通过记录区间内每一段后缀mod P的值就可以计算了
由于要加的是相同个数的数量,所以每个区间[l,r]要变成[l,r+1],字符串最后添0
注意离散化,注意2,5的特判
代码:

#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#define M 100003#define LL long longusing namespace std;int n,m;int block[M],sum[M];LL P,ans[M],a[M],b[M],cnt[M],T[M];char s[M];struct query{    int l,r,id;}q[M];int in(){    int t=0;char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();    return t;}bool cmp(query a,query b){    if (block[a.l]==block[b.l]) return a.r<b.r;    return block[a.l]<block[b.l];}void solve(){    for (int i=1;i<=n;i++)        if ((P==2&&!(s[i]-'0'&1))||(P==5&&(s[i]=='5'||s[i]=='0')))            cnt[i]+=i,++T[i];    for (int i=1;i<=n;++i) cnt[i]+=cnt[i-1],T[i]+=T[i-1];    for (int i=1;i<=m;++i)        q[i]=(query){in(),in(),i},        printf("%lld\n",cnt[q[i].r]-cnt[q[i].l-1]-(T[q[i].r]-T[q[i].l-1])*(q[i].l-1));}main(){    scanf("%lld",&P);    scanf("%s",s+1);    n=strlen(s+1);    m=in();    if (P==2||P==5) {solve();return 0;}     LL t=1;s[++n]='0';    for (int i=1;i<=m;++i) q[i]=(query){in(),in()+1,i};    for (int i=n;i>=1;--i)        a[i]=b[i]=(a[i+1]+t*(s[i]-'0'))%P,        t=t*10%P;    sort(b+1,b+n+1);    b[0]=unique(b+1,b+n+1)-b-1;    for (int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;    block[0]=sqrt(n);    for (int i=1;i<=n;++i) block[i]=(i+1)/block[0];    sort(q+1,q+m+1,cmp);    int L=1,R=0;LL S=0;    for (int i=1;i<=m;++i)    {        for (int j=L-1;j>=q[i].l;--j)            S+=sum[a[j]]++;        for (int j=L;j<q[i].l;++j)            S-=--sum[a[j]];        for (int j=R+1;j<=q[i].r;++j)            S+=sum[a[j]]++;        for (int j=R;j>q[i].r;--j)            S-=--sum[a[j]];        L=q[i].l;R=q[i].r;ans[q[i].id]=S;    }    for (int i=1;i<=m;++i) printf("%lld\n",ans[i]);}
0 0
原创粉丝点击