首页 > 学院 > 开发设计 > 正文

[bzoj4277]Ciecie

2019-11-08 20:21:31
字体:
来源:转载
供稿:网友

题目描述

给定一个长度为k的数字串N以及三个质数p,q,r,请你将N划分为三段非空字符串,使得第一段能被p整除,第二段能被q整除,第三段能被r整除,且每一段都不含前导0。 注意:单独的0是允许的。 2015<=p,q,r

瞎做

我们可以很容易通过前缀和后缀和处理判断一个前缀或后缀是不是p或r的倍数。 这个q的倍数呢? 假如[i,j]是q的倍数。 q|∑jk=ia[k]∗10j−k q|10j∗∑jk=ia[k]∗(10′)k 注意q>=2015且是质数,所以10^j可略去。 后面sigma式子只与k有关,因此可以处理那个东西的前缀和。 [i,j]是q的倍数,被转化为 q|sum[j]−sum[i−1] sum[i−1]≡sum[j](mod q) 然后就很容易做了,开个桶统计sum模q的合法后缀有多少个,瞎扫一波。 注意不能含有前导0但是一个0是允许的。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--) using namespace std;typedef long long ll;const int maxn=1000000+10,maxq=100000+10;int mi[maxn],PRe[maxn],suf[maxn],sum[maxn],b[maxq],a[maxn];int i,j,k,l,t,n,m,p,q,r,mo;ll ans;int quicksortmi(int x,int y){ if (!y) return 1; int t=quicksortmi(x,y/2); t=(ll)t*t%mo; if (y%2) t=(ll)t*x%mo; return t;}int get(){ char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); return ch-'0';}bool pd(int i){ if (i>1&&!a[1]) return 0; return (pre[i]==0);}bool dp(int i){ if (i<n&&!a[i]) return 0; return (suf[i]==0);}int main(){ scanf("%d%d%d%d",&n,&p,&q,&r); fo(i,1,n) a[i]=get(); mo=p; pre[0]=0; fo(i,1,n) pre[i]=((ll)pre[i-1]*10%mo+a[i])%mo; mo=q; t=quicksortmi(10,mo-2); l=1; fo(i,1,n){ l=(ll)l*t%mo; sum[i]=(sum[i-1]+(ll)a[i]*l%mo)%mo; } mo=r; suf[n+1]=0; l=1; fd(i,n,1){ suf[i]=(suf[i+1]+(ll)a[i]*l%mo)%mo; l=(ll)l*10%mo; } fd(i,n,1){ if (i>1&&i<n){ if (!a[i]&&pd(i-1)&&dp(i+1)) ans++; else if (a[i]&&pd(i-1)) ans+=b[sum[i-1]]; } if (i==n&&!a[i]) b[sum[i-1]]++; else if (a[i]&&dp(i)) b[sum[i-1]]++; } printf("%lld/n",ans);}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表