数位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的主要内容,如果未能解决你的问题,请参考以下文章

代码不计算小数位

如果小数位为 .00,则需要忽略字符串中的小数位

Libreoffice Calc Basic 如何通过代码附加 2 个小数位

jquery 精度计算代码,指定精确小数位

2021-09-11:给你一个32位的有符号整数x,返回将x中的数字部分反转后的结果。反转后整数超过 32 位的有符号整数的范围就返回0,假设环境不允许存储 64 位整数(有符号或无符号)。(代码片段

夜深人静写算法(二十九)- 数位DP