hdu 5119 Happy Matt Friends

来源:互联网 发布:椰旅部落永久域名新址 编辑:程序博客网 时间:2024/06/03 16:00

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 seusing namespace std;typedef long long LL;typedef pair<int, int> P;//headconst 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 0
原创粉丝点击