2019 cattle off more school four K number (dp or prefix and)

 

number

Title Description 

 

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.

Enter a description:

A single line consisting a string consisted of characters '0' to '9'.

Output Description:

The number of substrings that are multiples of 300 when considered as decimal integers.
Example 1

Entry

copy
600

Export

copy
4

Explanation

'600', '0', '0', '00' are multiples of 300. (Note that '0' are counted twice because it appeared two times)
Example 2

Entry

copy
123000321013200987000789

Export

copy
55

Remarks:

let the string in the input be s, 1 \leq |s| \leq 10^51s105.

To a string, I asked how many sub-divisible string 300, contains a leading zero.

dp [i] [j] denotes the number of number of% 300 == j formed in all positions before position i and

It may be pushed to the current state [i + 1] [(j * 10 + s [i + 1] - '0')% 300]

Therefore, the state transition equation dp [i] [(j * 10 + s [i] - '0')% 300] + = dp [i - 1] [j] .. Note that the initial value every time dp [i] [ s [i] - '0'] = 1.

#include<bits/stdc++.h>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#define INT(t) int t; scanf("%d",&t)

using namespace std;

const int maxn = 1e5 + 10;
LL dp[maxn][310];
char s[maxn];

int main() {
    while(~scanf("%s",s + 1)){
        int len = strlen(s + 1);
        clr(dp,0);
        for(int i = 1;i <= len;++ i){
            int tmp = s[i] - '0';
            dp[i][tmp] = 1;
            for(int j = 0;j < 300;++ j)
                dp[i][(j * 10 + tmp) % 300] += dp[i - 1][j];
        }
        LL ans = 0;
        for(int i = 1;i <= len;++ i)
            ans += dp[i][0];
        cout << ans << endl;
    }
    return 0;
}
View Code(dp)

 

Of course, this problem may be to make a prefix and, apparently 300% == 0 requires two conditions, at the end of two 0 foregoing == 0 3%, it is possible to record a prefix before the current position and 3% == 0, 1, 2 number, then add the number corresponding to

#include<bits/stdc++.h>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#define INT(t) int t; scanf("%d",&t)
 
using namespace std;
 
const int maxn = 1e5 + 10;
char s[maxn];
int sum[maxn];
int mp[maxn * 10];
 
int main() {
    while(~scanf("%s",s + 1)){
        clr(mp,0);
        int sz = strlen(s + 1);
        LL ans = 0;
        for(int i = 1;i <= sz;++ i){
            sum[i] = sum[i - 1] + s[i] - '0';
            sum[i] %= 3;
            if(s[i] == '0') ++ ans;
        }
        for(int i = 1;i + 1 <= sz;++ i){
            if(s[i] == '0' && s[i + 1] == '0'){
                ++ ans;
//                printf("===>%d , ",mp[sum[i - 1]]); debug(sum[i - 1]);
                ans += mp[sum[i - 1]];
                if(sum[i - 1] % 3 != 0) -- ans;
            }
//            debug(ans);
            ++ mp[sum[i]];
        }
//        debug(ans);
        cout << ans << endl;
    }
    return 0;
}
View Code (and prefix)

 

Guess you like

Origin www.cnblogs.com/rookie-acmer/p/11258415.html
Recommended