hdu 4901——The Romantic Hero

来源:互联网 发布:html5翻牌小游戏源码 编辑:程序博客网 时间:2024/05/22 06:31

题意:求一个数组左边一些数亦或的结果等于右边一些数与的结果的总和。
思路:最开始想着两遍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了几次。。
代码如下:

#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;}
0 0