zoukankan      html  css  js  c++  java
  • 51nod 1301 集合异或和

    题面

    解题思路

    动态规划,刚开始想的是dp[i][j][k]表示考虑了前i个数,A集合异或和为j,B集合异或和为k,时间复杂度O(n^3) ,得了50分。。正解应该是dp[i][j][k]表示前i个数,A^B=j,A与B第一位不同的数,B的这一位为k的方案数,因为要保证A < B,那么一定是A与B第x位之前的数相等,第x位B=1,A=0,首先枚举这一位数,然后用跑异或背包,因为前x位已经相等,所以答案应该在dp[n][2^i~2^(i+1)-1][1]中取。时间复杂度O(n^2logn)

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    const int MAXN=4098;
    const int mod=1e9+7;
    
    int n,m,logg;
    long long ans,dp[2][MAXN][2];
    
    int main(){
        scanf("%d%d",&n,&m);int mx=max(n,m);
        logg=(int)log2(mx)+1;
        for(register int i=0;i<=logg;i++){
            memset(dp,0,sizeof(dp));dp[0][0][0]=1;
            for(register int k=1;k<=mx;k++){
                int now=(k>>i)&1;
                for(register int j=0;j<(1<<logg);j++)
                    for(register int l=0;l<=1;l++){
                        dp[k&1][j][l]=dp[(k-1)&1][j][l];
                        if(k<=n) dp[k&1][j][l]+=dp[(k-1)&1][j^k][l];
                        if(k<=m) dp[k&1][j][l]+=dp[(k-1)&1][j^k][l^now];
                        dp[k&1][j][l]%=mod;
                    }
            }
            for(register int j=(1<<i);j<(1<<i+1);j++) ans+=dp[mx&1][j][1],ans%=mod;
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    Java的基本数据类型
    第五小组链表讨论作业
    WLST 命令和变量
    Linux之find命令详解
    Linux之netstat命令详解
    Linux之 sort,uniq,cut,wc命令详解
    Linux之grep命令详解
    Linux之awk命令详解
    Linux之sed命令详解
    关于表 datatable的条件查询
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676844.html
Copyright © 2011-2022 走看看