hdu 5119 Happy Matt Friends

http://acm.hdu.edu.cn/showproblem.php?pid=5119


dp[i][j]表示前i个数异或结果为j的方案数。

转移方程(这里的^是异或)
dp[i][j] = dp[i-1][j] + dp[i-1][j^k[i]]。

数组大小(这里的^表示幂)
因为2^19<10^6<2^20,也就是异或和用二进制表示最长为20位,最大值为2^20-1。
而每次状态更新都只与上一层有关,且答案只需要最后一层,所以只需要两层。
因此数组大小可设为dp[2][1<<20]。

思路
初始化dp[0][0]=1,所有的dp[i][j]写为dp[i%2][j],答案即为所有dp[n%2][j]之和,其中m<=j<=2^20-1。

注意点
方案总数会超过int范围,要用long long。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#define first fi
#define second se
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
//head
const int MAX = 1<<20;
LL dp[2][MAX];
int k[45];

int main()
{
    int t;
    scanf("%d",&t);
    for(int tt=1; tt<=t; tt++)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; i++)
            scanf("%d",&k[i]);
        dp[0][0] = 1;
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<MAX; j++)
                dp[i%2][j] = dp[(i-1)%2][j] + dp[(i-1)%2][j^k[i]];
//            for(int j=0; j<MAX; j++)
//                if(dp[i%2][j]!=0)
//                printf("dp[%d][%d]%d ",i,j,dp[i%2][j]);
//            printf("\n");
        }
        LL ans=0;
        for(int j=m; j<MAX; j++)
        {
            ans += dp[n%2][j];
//            if(dp[n%2][j]!=0)
//                printf("ans += dp[n][%d]%d\n",j,dp[n%2][j]);
        }
        printf("Case #%d: %I64d\n",tt,ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值