Codeforces 855E - Salazar Slytherin's Locket

855E - Salazar Slytherin's Locket

题意

给出一个区间,问这个区间内有多少个数满足,将这个数转化为某个进制后,所有数的数量都为偶数。

分析

谁能想到 数位DP 的裸题竟然放到了 E , 美滋滋。

考虑用一个二进制数记录每种数出现的次数的奇偶性,很容易用异或去操作。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN = 1e5 + 10;
ll dp[11][70][2048][2]; // dp[i][j][state][k] : i 进制 , j 长度 , 状态为 state , k 是否处于前导 0
int bit[70];

ll dfs(int jz, int len, int state, int pre0, int limit) {
    if(!len) return !state;
    if(!limit && dp[jz][len][state][pre0] != -1) return dp[jz][len][state][pre0];
    ll res = 0;
    int mx = limit ? bit[len] : (jz - 1);
    for(int i = 0; i <= mx; i++) {
        if(!i && pre0) {
            res += dfs(jz, len - 1, state, 1, limit && (i == mx));
        } else {
            res += dfs(jz, len - 1, state ^ (1 << i), 0, limit && (i == mx));
        }
    }
    if(!limit) dp[jz][len][state][pre0] = res;
    return res;
}

ll solve(ll n, int jz) {
    int l = 0;
    while(n) {
        bit[++l] = n % jz;
        n /= jz;
    }
    return dfs(jz, l, 0, 1, 1);
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    memset(dp, -1, sizeof dp);
    int Q;
    cin >> Q;
    while(Q--) {
        int b; ll l, r;
        cin >> b >> l >> r;
        cout << solve(r, b) - solve(l - 1, b) << endl;
    }
    return 0;
}
posted @ 2017-09-25 07:32  ftae  阅读(394)  评论(0编辑  收藏  举报