题目链接

题意:给一个数组a,从中选择一些元素,构成两个数组s, t,使s数组里的所有元素异或

等于 t数组里的所有元素 位于,求有多少种构成方式。要求s数组里 的所有的元素的下标

小于 t数组里的所有的元素的下标。

分析:比赛的时候,刚开始脑子很乱,后来想了一下思路也敲了,发现自己的程序结果不对

自己一点一点计算后发现自己的程序有一部分计算重复了,其实还是dp的思路不够清晰。

d[i][j]代表第i个数 新产生的结果为数字 j 的个数。

AC代码:

 #include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
#define LL long long
const int maxn = +;
const int mo = +;
using namespace std;
__int64 cnt;
int n, a[maxn];
__int64 d[maxn][maxn], dt[maxn][maxn], temp[maxn][maxn]; int main()
{
int T, i, j, x;
scanf("%d", &T);
while(T--)
{
cnt = ;
memset(d, , sizeof(d));
memset(dt, , sizeof(dt));
memset(temp, , sizeof(temp));
scanf("%d", &n);
for(i = ; i < n; i++)
scanf("%d", &a[i]);
for(i = ; i < n; i++)
{
for(j = ; j < ; j++)
{
if(i!= && temp[i-][j]) //让之前存在的和a[i]异或会产生新的存放在d数组里
{
x = (a[i]^j); //x有可能会大于j,所以不能用d数组直接累加
d[i][x] += temp[i-][j];
}
d[i][j] %= mo; //随时取余很重要,不然会wa
}
d[i][a[i]] ++; //加上自身
for(j = ; j < ; j++)
{
if(i != )
temp[i][j] += temp[i-][j] + d[i][j]; //temp数组用来维护目前所有的
else //结果,并且不可以用d直接加,否则会重复
temp[i][j] = d[i][j];
temp[i][j] %= mo;
}
}
memset(temp, , sizeof(temp));
for(i = n-; i >= ; i--)
{
for(j = ; j < ; j++)
{
if(temp[i+][j])
{
x = (a[i]&j);
dt[i][x] += temp[i+][j];
}
dt[i][j] %= mo;
}
dt[i][a[i]] ++;
for(j = ; j < ; j++)
{
temp[i][j] += temp[i+][j] + dt[i][j];
temp[i][j] %= mo;
}
}
for(i = n-; i >= ; i--)
for(j = ; j < ; j++)
{
dt[i][j] += dt[i+][j]; //这是防止重复的,让dt数组累加,d数组不累加。
dt[i][j] %= mo;
} for(i = ; i < n-; i++)
for(j = ; j < ; j++)
{
cnt += d[i][j]*dt[i+][j]; //用前面的乘以后面的
cnt %= mo;
}
cnt %= mo;
printf("%I64d\n", cnt);
}
return ;
}

顺便贴一下自己在比赛中wa的代码,思路不清。

 #include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
#define LL long long
const int maxn = +;
const int mo = +;
using namespace std;
__int64 cnt, f[maxn];
int n, a[maxn];
__int64 d[maxn][maxn], dt[maxn][maxn]; int main()
{
int T, i, j, tmp;
scanf("%d", &T);
while(T--)
{
cnt = ;
memset(d, , sizeof(d));
memset(dt, , sizeof(dt));
memset(a, , sizeof(a));
memset(f, , sizeof(f));
scanf("%d", &n);
for(i = ; i < n; i++)
scanf("%d", &a[i]);
d[][a[]] = ;
f[a[]] = ;
for(i = ; i < n; i++)
{
for(j = ; j < ; j++)
{
if(f[j])
{
tmp = (a[i]^j);
d[i][tmp] += f[j];
}
d[i][j] %= mo;
}
d[i][a[i]] ++;
f[a[i]] ++;
} memset(f, , sizeof(f));
dt[n-][a[n-]] = ;
f[a[n-]] = ;
for(i = n-; i >= ; i--)
{
for(j = ; j < ; j++)
{
if(f[j])
{
tmp = (a[i]&j);
dt[i][tmp] += f[j];
}
d[i][j] %= mo;
}
dt[i][a[i]] ++;
f[a[i]] ++;
} for(i = n-; i >= ; i--)
for(j = ; j < ; j++)
{
dt[i][j] += dt[i+][j];
dt[i][j] %= mo;
} for(i = ; i < n-; i++)
for(j = ; j < ; j++)
{
cnt += d[i][j]*dt[i+][j];
cnt %= mo;
}
cnt %= mo;
printf("%I64d\n", cnt);
}
return ;
}

hdu 4901 The Romantic Hero (dp)的更多相关文章

  1. HDU 4901 The Romantic Hero(二维dp)

    题目大意:给你n个数字,然后分成两份,前边的一份里面的元素进行异或,后面的一份里面的元素进行与.分的时候依照给的先后数序取数,后面的里面的全部的元素的下标一定比前面的大.问你有多上种放元素的方法能够使 ...

  2. HDU 4901 The Romantic Hero (计数DP)

    The Romantic Hero 题目链接: http://acm.hust.edu.cn/vjudge/contest/121349#problem/E Description There is ...

  3. HDU 4901 The Romantic Hero 题解——S.B.S.

    The Romantic Hero Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  4. HDU 4901 The Romantic Hero

    The Romantic Hero Time Limit: 3000MS   Memory Limit: 131072KB   64bit IO Format: %I64d & %I64u D ...

  5. 2014多校第四场1005 || HDU 4901 The Romantic Hero (DP)

    题目链接 题意 :给你一个数列,让你从中挑选一些数组成集合S,挑另外一些数组成集合T,要求是S中的每一个数在原序列中的下标要小于T中每一个数在原序列中下标.S中所有数按位异或后的值要与T中所有的数按位 ...

  6. HDU - 4901 The Romantic Hero(dp)

    https://vjudge.net/problem/HDU-4901 题意 给n个数,构造两个集合,使第一个集合的异或和等于第二个集合的相与和,且要求第一个集合的元素下标都小于第二个集合的元素下标. ...

  7. HDOJ 4901 The Romantic Hero

    DP....扫两次合并 The Romantic Hero Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 ...

  8. 【bzoj3866】The Romantic Hero dp

    题目描述 给你n个数,从中选出两个不相交非空集合S和T,使得S中的每一个元素都在T集合的前面,并且S集合中的所有数的亦或等于T集合中的所有数的与,求方案数 mod 10^9+7. 输入 The fir ...

  9. HDU4901 The Romantic Hero 计数DP

    2014多校4的1005 题目:http://acm.hdu.edu.cn/showproblem.php?pid=4901 The Romantic Hero Time Limit: 6000/30 ...

随机推荐

  1. Very large tabs in eclipse panes on Ubuntu

    http://stackoverflow.com/questions/11805784/very-large-tabs-in-eclipse-panes-on-ubuntu ou can edit E ...

  2. NodeJS下访问SQL Server

    1.下载node-sqlserver (1)msnodesql (msnodesql-0.2.1-v0.8-x64.msi)下载地址:下载  自行选择与自己系统相符的版本,点击安装. (2)msnod ...

  3. JAVASCRIPT、ANDROID、C#分别实现普通日期转换多少小时前、多少分钟前、多少秒

    貌似最近很流行这个,就写了个js函数实现之 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> ...

  4. asp.net中json格式化及在js中解析json

    类: public class UploadDocumentItem { public UploadDocumentItem() { } public string DocMuid { get; se ...

  5. IR的评价指标—MAP,NDCG,MRR

    http://www.cnblogs.com/eyeszjwang/articles/2368087.html MAP(Mean Average Precision):单个主题的平均准确率是每篇相关文 ...

  6. InnoDB与UUID

    CakePHP本身有一个uuid实现,所以一直以来,我都在尝试使用uuid做主键的可能性.虽然MySQL是我最常用的数据库,但是和 auto_increment_int主键相比,我对uuid主键更有好 ...

  7. Matlab计算两集合间的海明距离

    一.问题描述 B1[1 2 3 4 5 6 7 8 9] B2[12 13 14 21 31 41 51  1 1 81 1 1] 两个十进制矩阵,行数不一样,分别是n1和n2,列数必须一致,为nwo ...

  8. WSDL 文档解析

    学习webservice,就离不了WSDL文档,他是我们开发WebService的基础,虽说,现在现在有许多WebService的开源框架使得我们可以根据WSDL生成客户端代码,但是,了解WSDL文档 ...

  9. 剑指offer--面试题14

    #include "stdafx.h" #include <iostream> using namespace std; //调整数组顺序使奇数位于偶数前 void O ...

  10. spoj 1108

    要求输出一个牌的顺序 使每隔1.2.......n翻牌后出现1 2 3 4 5 6 7 8 9 .... n 将牌想象成n个空格  正向推 空n个位置放n 循环 需优化 #include <io ...