HackerRank Super Six Substrings dp

https://www.hackerrank.com/contests/hourrank-18/challenges/super-six-substrings

能被6整除的数有一个特点,就是能同时被3和被2整除

那么也就是能整除3的偶数。

设dp[i][j]表示以第i位结尾的所有子串中,%3的余数是j的方案数,

dp[i + 1][(j * 10 + nowNumber) % 3] = dp[i][j]

注意那个 * 10是必须的,因为从第i项转移过来,位数应该移动一位。就比如,12

1 % 3 = 1, 然后加入一个2,是1 * 10 + 2 = 12 % 3 = 0

但是这里又不是必须的,因为10 % 3 = 1,所以相当于没加。

现在说说那个0, 0是不能做前缀的,怎么破、

对于0,只算一个贡献,不加进去dp统计那里就行。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e5 + 20;
LL dp[2][3];
char str[maxn];
void work() {
    cin >> str + 1;
    int lenstr = strlen(str + 1);
    int now = 0;
    LL ans = 0;
    for (int i = 1; i <= lenstr; ++i) {
        now = !now;
        memset(dp[now], 0, sizeof dp[now]);
        int num = str[i] - '0';
        if (num == 0) {
            ans += dp[!now][0] + 1;
            memcpy(dp[now], dp[!now], sizeof dp[!now]);
            continue;
        }
        dp[now][num % 3] = 1;
        for (int j = 0; j <= 2; ++j) {
            dp[now][(j * 10 + num) % 3] += dp[!now][j];
        }
        if (num % 2 == 0) {
            ans += dp[now][0];
//            if (str[i - 1] == '0') ans--;
        }
//        cout << ans << endl;
    }
    cout << ans << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code

 

posted on 2017-03-14 08:57  stupid_one  阅读(181)  评论(0编辑  收藏  举报

导航