AtCoder Beginner Contest 164 - D Multiple of 2019

题意:给出一个由数字组成的字符串,让你求这个字符串里有多少个子串是 2019 2019 2019 的倍数。

很思维的一道题目

考虑 [ l , n ] [l,n] [l,n] [ r , n ] [r,n] [r,n] 2019 2019 2019 同余 ( l ≤ r l\leq r lr

x = [ r , n ] x=[r,n] x=[r,n] k = n − r + 1 k=n-r+1 k=nr+1 y = [ l , r ) y=[l,r) y=[l,r),则可以把 [ l , n ] [l,n] [l,n] 表示为 z = y × 1 0 k + x z=y\times 10^k+x z=y×10k+x

然后因为 x x x z z z 同余,所以 z − x z-x zx 2019 2019 2019 的倍数。

y × 1 0 k ≡ 0 ( m o d 2019 ) y\times 10^k \equiv 0\pmod {2019} y×10k0(mod2019)

然后因为 1 0 k ≢ 0 ( m o d 2019 ) 10^k \not \equiv 0 \pmod{2019} 10k0(mod2019)

所以 y ≡ 0 ( m o d 2019 ) y\equiv 0 \pmod{2019} y0(mod2019)

所以 [ l , r ) [l,r) [l,r) 就是 2019 2019 2019 的倍数了。

所以对于一个 l l l, 我们只需要找出有多少个 [ r , n ] ≡ [ l , n ] ( m o d 2019 ) [r,n] \equiv [l,n] \pmod {2019} [r,n][l,n](mod2019),就是以 l l l 开头的符合要求的子串的个数了。

那么我们可以把每一个 [ i , n ]   m o d   2019 ( i > l ) [i,n] \bmod 2019 (i>l) [i,n]mod2019(i>l) 算出来,并对于每一种余数进行计数。

最后求出答案就好了。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>

#define N 200010

using namespace std;

char s[N];
int ans,mod[2019];

int main()
{
    scanf("%s",s+1);
    int len=strlen(s+1);
    mod[0]=1;
    for(int i=len,x=0,cnt=1;i>=1;i--,cnt=cnt*10%2019)
    {
        x=((s[i]-'0')*cnt+x)%2019;
        ans+=mod[x];
        mod[x]++;
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值