• 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;
    }
  • 相关阅读:
    Java设计模式之装饰模式
    学习Emacs系列教程(二):导航
    Android ProgressDialog 延时消失
    java设计模式装饰模式
    Java 字节流和字符流的相互转换
    emacs配置颜色主题
    Android ProgressDialog的使用
    个人管理 时间管理GTD流程图
    jQuery - 列表控件推荐
    WPF - 模板查看工具:Show Me The Template及如何查看第三方主题
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4872492.html
Copyright © 2020-2023  润新知