hdoj 4901 多校联合4 1005

来源:互联网 发布:mac怎么用html5看视频 编辑:程序博客网 时间:2024/05/16 17:09

计数DP,思路还是很清晰的。只要有点DP基础,或者做过类似问题的,应该都能看出来是DP,可惜当时我没有做这个题。一直被那个线段树困着。

也希望以后能把线段树种活。这个题的思路就是设f[i][j]为 前i个数(从中选若干个数)异或值为j的集合数。h[i][j]为从第i个数开始到n(选若干个数),相与值为j的集合数。

最后两层循环(f[i][j]-f[i-1][j])*h[i+1][j]的累加和就是结果,之所以要减去f[i-1][j]是要去除重复的集合数。

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAX 1111#define MOD 1000000007__int64 f[MAX][MAX],h[MAX][MAX];int n,T;int a[MAX];int main(){    int i,j;    scanf("%d",&T);    while(T)    {        memset(f,0,sizeof(f));        memset(h,0,sizeof(h));        scanf("%d",&n);        for(i=1;i<=n;i++)            scanf("%d",&a[i]);        for(i=1;i<=n;i++)        {            f[i][a[i]]++;            for(j=0;j<1024;j++)            {                if(f[i-1][j])                {                    f[i][j]+=f[i-1][j];                    f[i][j]%=MOD;                    f[i][j^a[i]]+=f[i-1][j];                    f[i][j^a[i]]%=MOD;                }            }        }        for(i=n;i>=1;i--)        {            h[i][a[i]]++;            for(j=0;j<1024;j++)            {                 if(h[i+1][j])                {                    h[i][j]+=h[i+1][j];                    h[i][j]%=MOD;                    h[i][j&a[i]]+=h[i+1][j];                    h[i][j&a[i]]%=MOD;                }            }        }        __int64 ans=0;        for(i=1;i<n;i++)            for(j=0;j<1024;j++)            ans=(ans+((f[i][j]-f[i-1][j]+MOD)%MOD*h[i+1][j])%MOD)%MOD;        printf("%I64d\n",ans);        T--;    }    return 0;}


 

0 0
原创粉丝点击