题意
传送门 NC200204 dh的帽子文章来源:https://www.toymoban.com/news/detail-565799.html
题解
可以独立考虑每一位是否合法。维护数字上下界的状态,枚举三个数字,仅对合法的状态进行转移。数位 DP 求解即可,时间复杂度 O ( l o g R ) O(logR) O(logR)。文章来源地址https://www.toymoban.com/news/detail-565799.html
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int N = 20;
ll dp[20][8][8];
vector<int> big, small;
ll rec(int k, int llim, int ulim) {
if (k < 0) {
return 1;
}
if (dp[k][llim][ulim] != -1) {
return dp[k][llim][ulim];
}
ll res = 0;
for (int x = 0; x < 8; ++x) {
int ok = 1, l = 0, u = 0;
for (int i = 0; i < 3; ++i) {
int lb = (llim >> i & 1) ? small[k] : 0;
int ub = (ulim >> i & 1) ? big[k] : 1;
int t = x >> i & 1;
if (t < lb || t > ub) {
ok = 0;
break;
}
l |= (t == lb) << i;
u |= (t == ub) << i;
}
if (!ok) {
continue;
}
int xors = 0, ors = 0;
for (int i = 0; i < 3; ++i) {
int t = x >> i & 1;
xors ^= t;
ors |= t;
}
if (xors != ors) {
continue;
}
res += rec(k - 1, llim & l, ulim & u);
}
return dp[k][llim][ulim] = res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int l, r;
cin >> l >> r;
auto get = [](int x) {
vector<int> a;
while (x > 0) {
a.push_back(x & 1);
x >>= 1;
}
return a;
};
big = get(r), small = get(l);
int n = max(big.size(), small.size());
small.resize(n);
memset(dp, -1, sizeof(dp));
cout << rec(n - 1, 7, 7) << '\n';
return 0;
}
到了这里,关于NC200204 数位 DP的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!