• 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;
    }
  • 相关阅读:
    .Net Mvc 基于Filter实现对权限的扩展定制
    VS 2015 远程调试
    SVN 创建版本库
    .NET 调用支付宝沙箱接口
    selenium常用总结
    Python常用小技巧
    Centos7 安装Mysql 5.7
    Sqlserver 递归查询
    Sqlserver 中case when 的详细用法总结
    Asp.NetCoreWebApi入门
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676844.html
Copyright © 2020-2023  润新知