hustwinterC - Happy Matt Friends(dp解法)

Description

Matt has N friends. They are playing a game together.

Each of Matt’s friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends’magic numbers is no less than M , Matt wins.

Matt wants to know the number of ways to win.

Input

The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains two integers N, M (1 ≤ N ≤ 40, 0 ≤ M ≤ 10 6).

In the second line, there are N integers ki (0 ≤ k i ≤ 10 6), indicating the i-th friend’s magic number.

Output

For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y indicates the number of ways where Matt can win.

正解貌似是高斯消元....不会的说....PYY说不就是解方程么....然后我去看了下.....挺多概念没学线代的话还是挺眼生的...(orzpyy大神)记得高三的时候做过一个用矩阵加速求线性递推式的东西....当时10^18的数据秒过....还是挺让我惊讶了一下...
扯远了... 这题dp也能做,有点类似01背包(dp真是够渣,寒假看看能不能抽时间弄一下,依然是最大的短板)
只不过状态转移方程是 dp[i][j]=dp[i-1][j]+dp[i-1][j^a[i]]
然后正常些貌似会MLE。。。。。用到了滚动数组
其实滚动数组,完全...没有理解的难度啊 
竟然是我第一次使用,大概是因为基本没怎么做过DP的题吧,而滚动数组这个优化貌似主要在Dp的题里需要...
然后在搜滚动数组的时候,看到一篇博客里用异或来表示两个状态我觉得这一点也很赞.....
我自己想的话的大概就要又加,又mod,然后还得再来一个变量了吧.....差评满满
还有位运算....是挺神的东西....目前还处于一知半解的阶段....ORZ  M67大神

 1
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 const long long C=1<<21;
 7 long long dp[2][C];
 8 using namespace std;
 9
10 int main()
11 {
12     int t,a[49];
13     cin>>t;
14     int tt;
15     tt=t;
16     while (t--)
17
18     {
19         int n,m,roll;
20         roll=0;
21          memset(dp,0,sizeof(dp));
22         dp[0][0]=1;
23         cin>>n>>m;
24         for(int i=0;i<n;i++)
25             cin>>a[i];
26
27         for(int i=0;i<n;i++)
28         {
29             roll=roll^1;
30             for(int j=0;j<=(C/2);j++)
31                 dp[roll][j]=dp[roll^1][j]+dp[roll^1][j^a[i]];
32         }
33         long long ans=0;
34         for(int i=m;i<=(C/2);i++)
35             ans=ans+dp[roll][i];
36             cout<<"Case #"<<tt-t<<": "<<ans<<endl;
37
38     }
39     return 0;
40 }
41  
时间: 2024-10-25 08:16:02

hustwinterC - Happy Matt Friends(dp解法)的相关文章

neu1458 方格取数 dp解法

题意: 有N * N个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),把所有经过的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次. 走两次,所以状态表示要同时表示两次路径.dp[i][j][k][l] 表示第一次走到i,  j,第二次走到k, l得到的最大值,这里i + j == k + l 其实第四维是可以通过前三维算出来的,所以可以去掉 那么dp[i][j][k] 可以通过四种状

小明的密码-初级DP解法

#include #include #include using namespace std; int visited[5][20][9009];// 访问情况 int dp[5][20][9009]; // M N num num即M-1位的数字 int num_2[7]= {2,3,5,7,11,13,17}; int num_3[9]= {2,3,5,7,11,13,17,19,23}; int num_4[11]= {2,3,5,7,11,13,17,19,23,29,31}; //存储

Happy Matt Friends(DP)

Happy Matt Friends Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Others)Total Submission(s): 3700    Accepted Submission(s): 1407 Problem Description Matt has N friends. They are playing a game together. Each of Matt’s

HDOJ 5119 Happy Matt Friends DP

N*M暴力DP.... Happy Matt Friends Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Others) Total Submission(s): 82    Accepted Submission(s): 34 Problem Description Matt has N friends. They are playing a game together. Each

航空路线问题(dp解法)

题目链接:https://www.luogu.org/problemnew/show/P2770 题意: 从左到右给你n个点,有m条边连接这些点,问从最左边的点到达最右边的点再回到最左边的点最多可以经过几个点(除了起点外每个点最多只能被经过一次). 题解: 首先,我们可以把题意转化成从最左边的点走两条不相交的路线到达最右边的点,且使经过的点最多.标程是最大费用最大流. 为了限流,我们把每个点i拆成两个点xi,yi,x1->y1.xn->yn连一条容量为2,费用为1的边,其他点xi->yi

CF #610Div2 B2.K for the Price of One (Hard Version) (dp解法 &amp;&amp; 贪心解法)

题目大意:刚开始有 p 块钱,商店有 n 件物品,你每次可以只买一件付那一件的钱,也可以买 k 件只付最贵那件的钱,问你最多能买几件 (k<=n<=2e5) 首先我们要明确,如果你买了这一件商品,那么你一定买了比这件商品价格低的所有商品,因为这样买花的钱才会更少,方法才是最优的. 解法一:这道题用 背包dp 解应该是最直观的,先排序一下,状态要么由前一件转移过来,要么由前 k 件转移过来,即 dp[i] = min(dp[i-1]+a[i],dp[i-k]+a[i])然后我们只要找到买哪一件之

HDU 5119 Happy Matt Friends(DP)

题目链接:传送门 题意: 给定n个数,求从中选出任意个数异或起来值大于m的方案数. 分析: 动态规划,设dp[i][j] 表示第几次选第i个数的时候异或起来 值为j的方案数.dp[i][j^a[i]]+=dp[i][j];但是对空间有要求 我们可以用滚动数组来写. 代码如下: #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 1&l

HDU 5119 Happy Matt Friends(dp+位运算)

题意:给定n个数,从中分别取出0个,1个,2个...n个,并把他们异或起来,求大于m个总的取法. 思路:dp,背包思想,考虑第i个数,取或者不取,dp[i][j]表示在第i个数时,异或值为j的所有取法.dp[i][j] = dp[i - 1][j] + dp[i - 1][j ^ a[i]]); 其中dp[i - 1][j]表示不取第i个数,dp[i - 1][j & a[i]]表示取第i个数,由于40比较大,所以用滚动数组优化,后一个状态需要前一个来推导,而和前一个之前的所有的没有关系,所以之

HDU--5119Happy Matt Friends+dp

其实还是穷举子集类的dp,一般这种dp我们只需要用一个一维的滚动数组就可以了,但是这个题目状态转移的时候不但可能向后还有可能向前,所以这次得用二维数组. 状态方程 dp[i][j]=dp[i-1][j]+dp[i-1][j^num[i]],分别表示第i个数不取和第i个数取情况下状态. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn