这题差点(已经)把我的心态搞爆了 qwq,似乎因为忘记了数位 \(dp\) 的基本姿势而自闭了一天一夜
\(f_{i, pn, pm, pk}.first\) 为从第 \(i\) 位开始考虑,并且 \(i + 1\) 位以前的数 \(n,m\) 卡不卡上界,且目前的异或值卡不卡 \(k\) 的下界
\(f_{i, pn, pm, pk}.second\) 为对应的方案数
转移时枚举当前位 \(n,m\) 分别选什么即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
const int N = 65;
LL n, m, k;
bool vis[N][2][2][2];
pii f[N][2][2][2];
int mod, T, mx;
pii dfs_(int x, int pn, int pm, int pk) {
if (x < 0)
return pii(0, 1);
if (vis[x][pn][pm][pk])
return f[x][pn][pm][pk];
vis[x][pn][pm][pk] = 1;
int qn = pn ? (n>>x)&1 : 1, qm = pm ? (m>>x)&1 : 1;
pii ans(0, 0), tp;
for (int i = 0; i <= qn; i++)
for (int j = 0; j <= qm; j++)
if (((i^j) >= ((k>>x)&1)) || !pk) {
tp = dfs_(x - 1, pn && i == qn, pm && j == qm, pk && ((i^j) == ((k>>x)&1)));
ans.second = (ans.second + tp.second)%mod;
ans.first = (ans.first + tp.first + 1ll*tp.second*((1ll*(i^j)<<x)%mod))%mod;
}
return f[x][pn][pm][pk] = ans;
}
void solve_() {
memset(vis, 0, sizeof(vis));
mx = 0;
for (int i = 0; i <= 62; i++)
if ((n|m|k)&(1ll<<i))
mx = i;
dfs_(mx, 1, 1, 1);
printf("%lld\n", (f[mx][1][1][1].first - 1ll*f[mx][1][1][1].second*(k%mod)%mod + mod)%mod);
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%lld%lld%lld%d", &n, &m, &k, &mod);
n--, m--;
solve_();
}
}
标签:pii,储能,int,ans,pk,pn,pm 来源: https://www.cnblogs.com/iqx37f/p/14466190.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。