zoukankan      html  css  js  c++  java
  • hdu 5119 (类似于划分数的状态定义) (DP中的计数问题)

    题目描述:求n个数中异或值大于m的方案数有多少个?

    设状态f[i][j]代表前i个数异或值为j的方案数有f[i][j]种,那么对于j来说要么选第i个数与前面的i-1个数中的某些数构成jf[i-1][j^a[i]]],要么不选第i个数,直接由前面的i-1个数构成j,f[i-1][j];  f[i][j]=f[i-1][j^a[i]] + f[i-1][j] ; 注意到j的取值范围为10^6约等于2^(20),所以n个数亦或的最大值最多为201

    亦或的特性 : 任何数与0相亦或不变 ,任何数与本身相亦或为0

    设初值f[0][0]=1;

     之前用背包那种滚动数组来写,但是会发现d[i][j]= d[i-1][j] + d[i-1][j-V[i]]; 背包方程中不选的话j-V[i]<=j 所以j从大到小遍历,这一行的值只与上一行的值有关,

    然而这道题j^a[i]可能大于j,所以这一行的值不能保证只与上一行的值有关。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #define SIZE 50
    #define LL long long
    using namespace std;
    
    LL a[50];
    LL ans[50][1148576];
    void init()
    {
        memset(ans,0,sizeof(ans));
    }
    int main()
    {
        //freopen("test.txt","r",stdin);
        int t;
        scanf("%d",&t);
        int cas = 1;
        while(t --)
        {
            LL n,m;
            scanf("%I64d%I64d",&n,&m);
            init();
            for(int i = 1 ; i <= n ; i ++)
            {
                scanf("%I64d",&a[i]);
                //ans[a[i]] = 1;
            }
            LL all=pow(2,n);
            ans[0][0]=1;
            for(int i =  1; i <= n ; i ++)
            {
                for(int j = 0;j<1048576;j++)
                    ans[i][j] = ans[i-1][j^a[i]]+ans[i-1][j];
    
            }
            LL answer=0;
            for(int j=0;j<m;j++)
                answer+=ans[n][j];
            printf("Case #%d: %I64d
    ",cas ++,all-answer);
        }
        return 0;
    }
  • 相关阅读:
    PHP文件系统处理
    JavaScript数据类型
    JavaScript操作符
    JavaScript语法
    在 HTML 中使用JavaScript
    JavaScript概述
    PHP数组
    PHP基本语法
    Eclipse署动态web项目方法
    xml约束技术之dtd
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4872492.html
Copyright © 2011-2022 走看看