2019牛客多校训练第四场K.number(思维)

题目传送门

题意:

输入一个只包含数字的字符串,求出是300的倍数的子串的个数(不同位置的0、00、000等都算,并考虑前导零的情况)。

sample input:

600

123000321013200987000789

sample output:

4

55

题解:

O(n)做法:遍历一遍,求前缀和sum取余3,统计sum的个数num[sum],遇到本位和下一位都是0,则把之前统计的个数加上,最后加上单独0的个数。

O(300n)DP做法:如下

官方题解:

Code:

O(n)做法如下:

 /*6ms*/
1
#include<bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int M=1e5+5; 5 char s[M]; 6 int main() 7 { 8 while(~scanf("%s",s+1)) 9 { 10 int len=strlen(s+1),sum=0,num[3]={}; 11 ll cnt=0; 12 num[0]=1; 13 for(int i=1;i<=len;i++){ 14 sum=(sum+(s[i]-'0'))%3; 15 if(s[i]=='0'&&s[i+1]=='0'){ 16 cnt+=num[sum]; 17 } 18 if(s[i]=='0')cnt++; 19 num[sum]++; 20 } 21 printf("%lld\n",cnt); 22 } 23 return 0; 24 }

 DP做法如下【O(300n)】:

 /*224ms*/
1
#include<bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int M=1e5+5; 5 char s[M]; 6 int dp[M][302]; 7 int main() 8 { 9 while(~scanf("%s",s+1)) 10 { 11 memset(dp,0,sizeof(dp)); 12 dp[1][s[1]-'0']=1; 13 int len=strlen(s+1); 14 for(int i=2;i<=len;i++){ 15 dp[i][s[i]-'0']++; 16 for(int j=0;j<300;j++){ 17 int flag=(j*10+s[i]-'0')%300; 18 dp[i][flag]+=dp[i-1][j]; 19 } 20 } 21 ll ans=0; 22 for(int i=1;i<=len;i++) 23 ans+=dp[i][0]; 24 printf("%lld\n",ans); 25 } 26 return 0; 27 }

猜你喜欢

转载自www.cnblogs.com/HOLLAY/p/11264713.html