HDU-4901 The Romantic Hero DP

来源:互联网 发布:淘宝怎么开店上传图片 编辑:程序博客网 时间:2024/05/21 15:06

首先吐槽一下这个神一样的题目前缀,特么一直在强调萝莉控是闹哪样啊喂(╯‵□′)╯︵┻━┻

题意不难,从一个数列中选出一部分作为S,S的元素进行 ‘异或’ 操作,在选出一部分作为T,T里的元素进行 ’与‘ 操作,要求S的元素必须在T的元素的左边。

最初没有想到用DP写,因为没有想到用下标表示数字,其实用用二维数组DP,横坐标表示操作到第几个数,纵坐标储存该数字得到多少次,最开始把初状态放进去就好,最后对应位置相乘加起来就好了,G++TLE了,换成C++2437ms过了,另外写的时候思路还不是很清晰,代码很乱。

#include <iostream>#include <cstdio>#include <queue>#include <algorithm>#include <cmath>#include <cstring>#include <cstdlib>#include <iomanip>using namespace std;const int mod=1000000000+7;long long dp1[1111][1111];long long dp3[1111][1111];long long dp2[1111][1111];long long m1[2048];long long m2[2048];int a[1111];int n;long long sum;int main(){int t;scanf("%d",&t);while(t--){scanf("%d",&n);memset(dp1,0,sizeof(dp1));memset(dp2,0,sizeof(dp2));memset(dp3,0,sizeof(dp3));for(int i=1;i<=n;i++){scanf("%d",&a[i]);}dp1[1][a[1]]=1;//初状态处理 dp3[1][a[1]]=1;//dp1[1][0]=1;dp2[n][a[n]]=1;//dp2[n][0]=1;for(int i=2;i<n;i++){dp3[i][a[i]]+=1;//用来表示前几个都不取的情况 dp1[i][a[i]]+=1;memset(m1,0,sizeof(m1));for(int j=0;j<=1024;j++){if(dp1[i-1][j]!=0){dp3[i][a[i]^j]+=dp1[i-1][j];//用另一个DP储存,因为最后处理时要求最后一个必须取到 dp1[i][a[i]^j]+=dp1[i-1][j];dp1[i][a[i]^j]%=mod;dp3[i][a[i]^j]%=mod;m1[j]=dp1[i-1][j];m1[j]%=mod;}}for(int j=0;j<=1024;j++){dp1[i][j]+=m1[j];dp1[i][j]%=mod;//处理到第i个的总情况 }}for(int i=n-1;i>1;i--){dp2[i][a[i]]+=1;//用来表示前几个都不取的情况 memset(m2,0,sizeof(m2));for(int j=0;j<=1024;j++){if(dp2[i+1][j]!=0){dp2[i][a[i]&j]+=dp2[i+1][j];//后面的只需要保证不为空就行了,不需要特殊处理 dp2[i][a[i]&j]%=mod;m2[j]=dp2[i+1][j];m2[j]%=mod;}}for(int j=0;j<=1024;j++){dp2[i][j]+=m2[j];dp2[i][j]%=mod;}}sum=0;for(int i=1;i<n;i++){for(int j=0;j<=1024;j++){if(dp3[i][j]&&dp2[i+1][j]){sum+=dp3[i][j]*dp2[i+1][j];//对应位置相乘相加,+1刚好是所有的情况 sum%=mod;}}//cout<<sum<<endl;}cout<<sum<<endl;}}



0 0
原创粉丝点击