您的位置:首页 > 其它

hdu 4901——The Romantic Hero

2015-07-31 13:42 375 查看
题意:求一个数组左边一些数亦或的结果等于右边一些数与的结果的总和。

思路:最开始想着两遍DP,dp1[i][j]表示包含第i个数的左边的数亦或结果是j的方法数,dp2[i][j]表示包含第i个数的右边的数与结果为j的方法数。这样的方法复杂度是O(n^2*1024),会超时。后来将dp2[i][j]改成到底i个数右边(不一定包含第i个数)与结果为j的方法数,复杂度就变成O(n*1024)。

在求dp的时候忘记取余数了wa了几次。。

代码如下:

[code]#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<map>
#include<cmath>
#include<assert.h>
#include<iomanip>
#include<assert.h>
using namespace std;
typedef long long ll;

const ll mod = 1000000007;
ll dp1[1005][1029];
ll dp2[1005][1029];
ll dp[1029];
int a[1005];

int main()
{
//    freopen("data.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        memset(dp1,0,sizeof(dp1));
        memset(dp2,0,sizeof(dp2));
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;++i){
            scanf("%d",&a[i]);
        }

        dp1[0][a[0]] = 1;
        dp[a[0]] = 1;
        for(int i = 1;i<n;++i){
            dp1[i][a[i]] =1;
            for(int j=0;j<1024;++j){
                int c = a[i]^j;
                dp1[i][c] += dp[j];
                dp1[i][c] %= mod;
            }
            for(int j = 0; j< 1024;++j){
                dp[j] += dp1[i][j];
                dp[j] %= mod;
            }
        }
        dp2[n-1][a[n-1]] = 1;
        for(int i = n-2;i>=0;--i){
            for(int j =0;j<1024;++j){
                dp2[i][j] = dp2[i+1][j];
                dp2[i][j] %= mod;
            }
            dp2[i][a[i]]++;
            for(int j =0;j<1024;++j){
                int c = a[i]&j;
                dp2[i][c] += dp2[i+1][j];
                dp2[i][c] %= mod;
            }
        }

        ll ans = 0;
        for(int i = 0;i<n-1;++i){
            for(int j =0;j<1024;++j){
                ans += (dp1[i][j]*dp2[i+1][j])%mod;
                ans%=mod;
            }
//            cout<<i<<' '<<ans<<endl;
        }
        cout<<ans<<endl;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: