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;
}