hdu4901 背包

来源:互联网 发布:淘宝国际版开店 编辑:程序博客网 时间:2024/05/28 17:05

枚举分界线,将分界线上的元素强行划分给一边,另一边随意,然后求组合数即可。

附代码:

#include <iostream>#include <cstring>#include <cstdio>using namespace std;long long int dp[1005][1025];       //记录前i项异或结果为t的组合数long long int ddp[1005][1025];      //记录后i项与的结果为t的包含第i项的组合数long long int dpp[1005][1025];      //记录后i项与的结果为t的可包含可不包含第i项的组合数int a[1001];int n;const int mod=1000000000+7;int main(){    int T;    cin>>T;    while (T--)    {        scanf("%d",&n);        for (int i=1;i<=n;i++)            scanf("%d",&a[i]);        memset(dp,0,sizeof(dp));        memset(ddp,0,sizeof(ddp));        memset(dpp,0,sizeof(dpp));        dpp[n][a[n]]=1;        ddp[n][a[n]]=1;        dp[1][a[1]]=1;        for (int i=2;i<=n;i++)        {            dp[i][a[i]]=1;            for (int t=1023;t>=0;t--)            {                int x=t^a[i];                dp[i][x]+=dp[i-1][t];   //用上当前项                dp[i][t]+=dp[i-1][t];   //不用当前项                dp[i][x]%=mod;                dp[i][t]%=mod;            }        }        for (int i=n-1;i>=1;i--)        {            dpp[i][a[i]]=1;            ddp[i][a[i]]=1;            for (int t=1023;t>=0;t--)            {                int x=t&a[i];                ddp[i][x]+=dpp[i+1][t];     //用上当前项,由前面所有组合情况推出                dpp[i][x]+=dpp[i+1][t];     //用上当前项                dpp[i][t]+=dpp[i+1][t];     //不用当前项                ddp[i][x]%=mod;                dpp[i][x]%=mod;                dpp[i][t]%=mod;            }        }        long long int ans=0;        for (int i=1;i<n;i++)        {            for (int t=0;t<=1023;t++)            {                ans+=dp[i][t]*ddp[i+1][t];                ans%=mod;            }        }        cout<<ans<<endl;    }}


0 0
原创粉丝点击