AtCoder Beginner Contest 164 - D Multiple of 2019

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

很思维的一道题目

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

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

然后因为 \(x\)\(z\) 同余,所以 \(z-x\)\(2019\) 的倍数。

\(y\times 10^k \equiv 0\pmod {2019}\)

然后因为 \(10^k \not \equiv 0 \pmod{2019}\)

所以 \(y\equiv 0 \pmod{2019}\)

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

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

那么我们可以把每一个 \([i,n] \bmod 2019 (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;
}
posted @ 2022-10-31 08:15  ez_lcw  阅读(22)  评论(0编辑  收藏  举报