[51Nod 1301] 集合异或和 (dp)

传送门

Solution

一道比较好的dp题 想了半天组合数QAQ
首先要知道的是 A<B一定是B有一位是1且A的这位是0且前面都相等
那么肯定是要枚举这一位在哪里然后求出方案数
方案数考虑类似背包的方法分三种情况转移具体见代码

Code

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
typedef long long LL;

const int N=5000,MOD=1e9+7;
int n,m;
LL ans,f[2][N][2];

int main() {
    cin>>n>>m;
    for(int i=0;(1<<i)<=max(n,m);i++) {
        memset(f,0,sizeof(f));
        f[0][0][0]=1;
        for(int j=1;j<=max(n,m);j++) {
            int x=(j>>i)&1,c=j&1;
            for(int k=0;k<=2048;k++) F(X,0,1) {
                f[c][k][X]=f[c^1][k][X];
                if(j<=n) f[c][k][X]=(f[c][k][X]+f[c^1][k^j][X])%MOD;
                if(j<=m) f[c][k][X]=(f[c][k][X]+f[c^1][k^j][X^x])%MOD;
            }
        }
        F(j,(1<<i),(1<<(i+1))-1) ans=(ans+f[(max(n,m)&1)][j][1])%MOD;
    }
    printf("%lld",ans%MOD);
    return 0;
}

原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9606839.html

时间: 2024-11-07 16:33:57

[51Nod 1301] 集合异或和 (dp)的相关文章

51nod 1301 集合异或和——异或dp

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1301 好题!看了TJ才会. 因为是不可重集合,所以当然有前 i 个表示A和B都考虑的前 i 个,新加一个讨论放A.放B.不放. A<B在异或上看就是有一位,它前面的A和B都一样,该位A是0.B是1.该位可以枚举.然后就能dp了. 注意边界细节--和标程对拍真愉快-- #include<iostream> #include<cstdio> #in

从集合的角度思考DP问题

从集合的角度思考DP问题 如上图展示了DP问题思考的一个简单步骤来自y总直播,"就像计算乘法一样,学会分析DP问题就像学会列竖式一样,让处理DP问题更简单"这就话让我瞬间意识到分析问题的重要性,处理DP问题不应该是想出转移过程,应该是一步步分析出来的.这篇博客记录以后做题过程中我对DP分析方法的理解和总结 #one. 杨老师的照相排列 (第一篇废话较多) DP问题 这道题目前我解释不出为什么要用DP做,但Count是DP一类题型 分析过程 DP一般就是一个状态向另一个状态转移,在这个过

51nod 1412 AVL树的种类(dp)

题目链接:51nod 1412 AVL树的种类 开始做的时候把深度开得过小了结果一直WA,是我天真了.. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 typedef long long ll; 7 const int mod = 1e9+7; 8 const int N = 2001; 9 ll

51nod 1020 逆序排列(dp,递推)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1020 题意:是中文题. 题解:很显然要设dp[i][j]表示,i个数有j个逆序对有几种然后就是状态的转移, dp[i][j]=dp[i-1][max(0,j-(i-1)]+.....+dp[i-1][max(j,(i-1)*(i-2)/2]; 还会用到前缀和,还有注意最后结果加mod再膜mod,结果可能会负数. #include <iostream> #i

hihocoder #1301 : 筑地市场 数位dp+二分

题目链接: http://hihocoder.com/problemset/problem/1301?sid=804672 题解: 二分答案,每次判断用数位dp做. #include<iostream> #include<cstring> #include<cstdio> using namespace std; typedef long long LL; const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; //dp[x][0]表示高位还没有出

51nod 1051 最大子矩阵和(dp)

题目链接:51nod 1051 最大子矩阵和 实质是把最大子段和扩展到二维.读题注意m,n... 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #define CLR(a,b) memset((a),(b),sizeof((a))) 6 using namespace std; 7 const int N = 501; 8 int dp[N]

51nod 1043 幸运号码(数位DP)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题目: 1个长度为2N的数,如果左边N个数的和 = 右边N个数的和,那么就是一个幸运号码. 例如:99.1230.123312是幸运号码. 给出一个N,求长度为2N的幸运号码的数量.由于数量很大,输出数量 Mod 10^9 + 7的结果即可. Input 输入N(1<= N <= 1000) Output 输出幸运号码的数量 Mod 10^9 + 7

51nod 1732 婚姻介绍所 (暴力 / DP)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1732 题目: 51nod除了在做OJ之外,还开展了很多副业.婚姻介绍所就是其中之一. 对于一个客户,我们可以使用一个字符串来描述该客户的特质. 假设现在我们有两个客户A和B. A的特质字符串为:abcdefg B的特质字符串为:abcxyz 则A和B的匹配度f(A, B)为A和B的最长公共前缀的长度,即len('abc') = 3 由于最近51nod经费紧张,

51Nod 1450 闯关游戏 —— 期望DP

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1450 期望DP: INF 表示这种情况不行,转移时把不行的概率也转移到自身即可: 还要按得星概率排个序,先决策概率大的就是最优策略,因为后面的都基于它. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using n