AtCoder Beginner Contest 158 E.Divisible Substring

在这里插入图片描述
在这里插入图片描述

题意:

给一个长度为 n n 的字符串 s s ,以及一个质数 p p ,求有多少个子串在十进制下对可以整除 p p
首先可以得知 1 0 x m o d p 0 ( p 2 a n d p 5 ) 10^xmod p≠0(p≠2 and p≠5) ,那么对于 s l . . . r s_{l...r} 子串,当且仅当 S l . . . n s r . . . n ( m o d p ) S_{l...n}≡s_{r...n}(mod p) 成立时,满足要求。

证明如下:
S l . . . r × 1 0 r l = S l . . . n S r . . . n S_{l...r}×10^{r−l}=S_{l...n}−S_{r...n} ,若 S l . . . n S r . . . n 0 ( m o d P ) S_{l...n}−S_{r...n}≡0(mod P) ,由于 1 0 x m o d p 0 10^xmod p≠0 ,可以得出 S l . . . r m o d p = 0 S_{l...r} mod p=0 ,若 S l . . . n S r . . . n ≢ 0 ( m o d p ) S_{l...n}−S_{r...n} \not\equiv 0(mod p) ,显然 S l . . . r m o d p 0 S_{l...r} mod p≠0
p = 2 , p = 5 p=2,p=5 4 3进行特判,然后倒着遍历字符串,每次加上之前余数和当前余数相同的个数。

int m, p;
int ans, res, x;
int n, q, k, t;
string s;
int cnt[10005];
int main()
{
    sdd(n, p);
    cin >> s;
    ans = 0;
    if (p == 2 || p == 5)
    {
        rep(i, 0, n - 1)
        {
            if ((s[i] - '0') % p == 0)
                ans += i + 1;
        }
    }
    else
    {
        res = 0;
        t = 1;
        cnt[0] = 1;
        per(i, n - 1, 0)
        {
            res = (res + (s[i] - '0') * t) % p;
            ans += cnt[res]++;
            t = t * 10 % p;
            //pdd(res,t);
        }
    }
    pd(ans);
    return 0;
}

发布了711 篇原创文章 · 获赞 425 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/qq_43627087/article/details/104752667
今日推荐