bzoj 4277: [ONTAK2015]Cięcie 亂搞
阿新 • • 發佈:2019-01-22
題意
給定一個長度為k的數字串N以及三個質數p,q,r,請你將N劃分為三段非空字串,使得第一段能被p整除,第二段能被q整除,第三段能被r整除,且每一段都不含前導0。注意:單獨的0是允許的。
3<=k<=1000000,2015<=p,q,r<=100000
分析
因為p,q,r均為很大的素數,那麼如果有
那麼我們可以先預處理處哪些段可以整除p,r,統計q的話就用字首和瞎搞一搞就好了。
程式碼
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1000005;
int n,p,q,r,s1[N],s2[N],s3[N],t[N];
char ch[N];
int main()
{
scanf("%d%d%d%d",&n,&p,&q,&r);
scanf("%s",ch+1);
for (int i=1;i<=n;i++) s1[i]=(s1[i-1]*10+ch[i]-'0' )%p;
for (int i=n,x=1;i>=1;i--,x=x*10%r) s2[i]=(s2[i+1]+(ch[i]-'0')*x)%r;
for (int i=n,x=1;i>=1;i--,x=x*10%q) s3[i]=(s3[i+1]+(ch[i]-'0')*x)%q;
for (int i=2;i<=n;i++) if (!s2[i]&&(ch[i]!='0'||i==n)) t[s3[i]]++;
LL ans=0;
for (int i=1;i<n;i++)
{
if (!s2[i+1 ]&&(ch[i+1]!='0'||i+1==n)) t[s3[i+1]]--;
if (!s1[i]&&(ch[i]!='0'||i==1)) ans+=t[s3[i+1]];
}
printf("%lld",ans);
return 0;
}