• 数位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}) 。我一开始答案只记录到最大值,导致一部分漏解了。

    简化代码的写法就是每次都走到数据范围最大的解答,为了更加优化可以去找一下最大值作为边界。

  • 相关阅读:
    多表关联查询_resultMap_集合对象
    mybatis多表关联查询之resultMap单个对象
    十二.filter
    十二.函数式编程
    十一.列表生成式
    十,迭代
    九.高级特性
    八.函数
    七.条件判断和循环
    六.使用list和tuple
  • 原文地址:https://www.cnblogs.com/tieway59/p/10785560.html
Copyright © 2020-2023  润新知