题目链接

题意:给一个数组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. Sublime Text 2 入门

    SublimeText 2 的介绍视频: http://player.youku.com/player.php/partnerid/XOTcy/sid/XMzU5NzQ5ODgw/v.swf   以下 ...

  2. oracle里如何将两个日期的时间差返回**时**分的格式

    SELECT EXTRACT(DAY FROM (sysdate-to_date('2012-03-29 00:00:00','YYYY-MM-DD HH24:MI:ss')) DAY TO SECO ...

  3. Qt入门之信号与槽机制

    一. 简介 就我个人来理解,信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁. 信号和槽机制是 Qt 的核心机制,可以让编程人员将互不 ...

  4. php多条件查询

    $sql)"; if(!empty($uid)) { $sql .=" and uid= ".$uid; } if(!empty($time1) && e ...

  5. svn: E155004: ..(path of resouce).. is already locked

    svn: E155004: ..(path of resouce).. is already locked I'm getting an error when trying to commit a c ...

  6. 【POJ】【3308】Paratroopers

    网络流/二分图最小点权覆盖 sigh……这题……TLE&RE了好几发 建一个二分图,左边的每个结点代表行,右边的代表列,如果在(i,j)这个位置有一个外星人,那么我们就连一条边 (左 i -& ...

  7. (一)、http原理

    谣言粉碎机前些日子发布的<用公共WiFi上网会危害银行账户安全吗?>,文中介绍了在使用HTTPS进行网络加密传输的一些情况,从回复来看,争议还是有的.随着网络越来越普及,应用越来越广泛,一 ...

  8. windowopen

    1.最基本的弹出窗口代码] <SCRIPT LANGUAGE="javascript"> <!-- window.open ('page.html') --> ...

  9. CentOS中基于不同版本安装重复包的解决方案

    http://blog.chinaunix.net/uid-21710705-id-3039675.html

  10. Java Excel

    http://www.cnblogs.com/mingforyou/archive/2013/08/26/3282922.html