[SDOI2016]储能表
题意
link
给出 , 有 组询问。
求
数位dp
状态
实际上能求出所有 的和 ,和个数 ,那么答案就是 。
由于是异或,可以分开考虑二进制下每一位。
考虑求出 , 设 表示现在是第 位 (低到高),是否到 的上界,是否到 的上界,是否到 的下界的个数。
同理,只不过记得是和。
初始和最终状态
这里我是从高位到低位递归,对于最低位 ,由于要满足 的限制,
只有 。
最后要求的是 。
转移
到了上界就有 在这一位的限制,否则就没有限制, 同理。
枚举两个数在这一位的取值,就能转移了。
转移就懒得写了太多了,看代码。
对于 , 求出 转移到这一位的方案数 乘上位权即可。
分析
状态很少 , 转移也是 级别的。
用一下记忆化搜索就很快了。
时间复杂度大概是 。
代码
记得取模,求答案时对k也要。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 65;
const int INF = 0x7fffffff;
//const int mod = 1000000007;
int mod;
const double eps = 1e-9;
template <typename T>
void Read(T &x) {
x = 0; T f = 1; char a = getchar();
for(; a < '0' || '9' < a; a = getchar()) if (a == '-') f = -f;
for(; '0' <= a && a <= '9'; a = getchar()) x = (x * 10) + (a ^ 48);
x *= f;
}
inline int add(const int &a, const int &b) {
static int c;
c = a + b;
if (c >= mod) c -= mod;
if (c < 0) c += mod;
return c;
}
inline int mul(const int &a, const int &b) {
return 1ll * a * b % mod;
}
int qpow(int a, int b) {
int sum(1);
while(b) {
if (b & 1) sum = mul(sum, a);
a = mul(a, a);
b >>= 1;
}
return sum;
}
ll n, m, k;
int f[MAXN][2][2][2];
int F(int N, int a, int b, int c) {
if (N == -1) return !a && !b && !c;
int nn = (n >> N) & 1, mm = (m >> N) & 1, kk = (k >> N) & 1, sum = 0;
if (~f[N][a][b][c]) return f[N][a][b][c];
for (int x = 0; x <= 1; x ++)
for (int y = 0; y <= 1; y ++) {
int z = x ^ y;
if ((a && x > nn) || (b && y > mm) || (c && (z < kk)))
continue;
int A = a & (x == nn), B = b & (y == mm), C = c & (z == kk);
sum = add(sum, F(N - 1, A, B, C));
}
return f[N][a][b][c] = sum;
}
int g[MAXN][2][2][2];
int G(int N, int a, int b, int c) {
if (N == -1) return 0;
int nn = (n >> N) & 1, mm = (m >> N) & 1, kk = (k >> N) & 1, sum = 0;
if (~g[N][a][b][c]) return g[N][a][b][c];
for (int x = 0; x <= 1; x ++)
for (int y = 0; y <= 1; y ++) {
int z = x ^ y;
if ((a && x > nn) || (b && y > mm) || (c && (z < kk)))
continue;
int A = a & (x == nn), B = b & (y == mm), C = c & (z == kk);
sum = add(sum, G(N - 1, A, B, C));
sum = add(sum, mul(F(N - 1, A, B, C), (z ? qpow(2, N) : 0)));
}
return g[N][a][b][c] = sum;
}
int main() {
int T;
cin >> T;
while(T --) {
cin >> n >> m >> k >> mod;
memset(f, -1, sizeof(f));
memset(g, -1, sizeof(g));
cout << add(G(62, 1, 1, 1), -mul(F(62, 1, 1, 1), k % mod)) << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?