数位DP::SoSDP
Posted tieway59
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数位DP::SoSDP相关的知识,希望对你有一定的参考价值。
数位DP:: SoSDP
学习博客(待补)
下面做一些例题:
SPECIAL PAIRS
题意
给n个数字,求这些数字有多少对的\(AND\) 结果是0。数字不大于1e6。顺序反相反视为不同的对。
思路
做一个桶排计数。对于每个数\(a_i\) ,与他\(AND\) 是0的数,就是反$ a_i$ 的子集。也即是SoSDP里的F所统计的量了。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6+5;;
int a[MAXN];
int x[MAXN];
long long dp[MAXN];
int kase,n;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>kase;
while(kase--){
cin>>n;
memset(a,0,sizeof a);
memset(dp,0,sizeof dp);
for(int i=1;i<=n;i++){
cin>>x[i];
dp[x[i]]=++a[x[i]];
}
for(int i=0;i<=20;i++)
for(int mask=0;mask<=(1<<20);mask++){
if(mask&(1<<i)){
dp[mask]+=dp[mask^(1<<i)];
}
}
int mask=(1<<20)-1;
long long ans=0;
for(int i=1;i<=n;i++){
ans+=dp[(~x[i])&mask];
}
cout<<ans<<endl;
}
return 0;
}
/*
4
5
41 47 34 40 29
4
999956 999959 999993 999993
3
4 1 3
3
1 0 0e
*/
注意几个细节:
位数一定取到最大值的长度(假设是len),而答案要记录到\((1)_B^{len}\) 。我一开始答案只记录到最大值,导致一部分漏解了。
简化代码的写法就是每次都走到数据范围最大的解答,为了更加优化可以去找一下最大值作为边界。
以上是关于数位DP::SoSDP的主要内容,如果未能解决你的问题,请参考以下文章
Libreoffice Calc Basic 如何通过代码附加 2 个小数位
2021-09-11:给你一个32位的有符号整数x,返回将x中的数字部分反转后的结果。反转后整数超过 32 位的有符号整数的范围就返回0,假设环境不允许存储 64 位整数(有符号或无符号)。(代码片段