2019牛客暑期多校训练营(第四场) K题 number

题目描述
300iq loves numbers who are multiple of 300.
One day he got a string consisted of numbers. He wants to know how many substrings in the string are multiples of 300 when considered as decimal integers.
Note that leading and trailing zeros are allowed (both in original string and substrings you chose) and the same substring appearing in different places can be counted multiple times.
输入描述:
A single line consisting a string consisted of characters ‘0’ to ‘9’.
输出描述:
The number of substrings that are multiples of 300 when considered as decimal integers.
示例1
输入

600
输出

4
说明
‘600’, ‘0’, ‘0’, ‘00’ are multiples of 300. (Note that ‘0’ are counted twice because it appeared two times)
示例2
输入

123000321013200987000789
输出

55
备注:
let the string in the input be s, 1≤∣s∣≤ 1 0 5 10^5 105
.
分析:
让求的是300的倍数,但是呢我们可以拆成既是3的倍数也是100的倍数
那么这样就可以找到一些规律:
1.对于3的倍数来说就是各个位上的数值加起来和对3取余答案是0
2.对于100的倍数来说就是要求后两位至少为0
有了这个规律之后就完成了一半,还有一半就是这个:
大家可以注意到两个相同余数之间都是算作答案里面的,这句话是是什么意思呢????
举个栗子:
假设给出的整数是:
1 0 1 0 0 1 2 0 0 0
对3取余的结果:1 1 2 2 2 0 2 2 2 2
对于下面“对3取余的结果”是求前缀和才得到的,大家在去理解一下,什么叫“两个相同余数之间”
拿上面的例子,取余结果为2的区间是 1 0 0 1 2 是这个区间
有人会问,为甚不包括后面的三个0呢,因为第一次遇到两个连续的0,就是我们更新答案的地方,必须到这个地方停下来
此时取余为2的个数为4(2 2 2 0 2,4个2),那么这个区间就是下面这个五个答案:
001200 01200 1200 00
又要有人问,为甚没有后面两个0 0,这样就是7个了,因为单个0我们一开始就需要特殊处理一下
下面结合代码便于理解

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=1e5+10;
char str[N];
typedef long long ll;
ll ans=0, cnt[N];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    scanf("%s",str);
    cnt[0]=1;
    int len=strlen(str);
    for(int i=0;i<len;i++){
        if(str[i]=='0')
            ans++;//先处理单个0的情况
    }
    int sum=0;
    for(int i=0;i<len-1;i++){
        sum+=str[i]-'0';
        sum%=3;
        if(str[i]=='0' && str[i+1]=='0')
            ans+=cnt[sum];
        cnt[sum]++;
    }
    printf("%lld\n",ans);
    return 0;
}


你可能感兴趣的:(思维,数学)