HDU 4901 The Romantic Hero 计数DP

来源:互联网 发布:stm32指纹识别源码 编辑:程序博客网 时间:2024/04/30 11:47

题意:给你一些数,分成2个集合,左边的集合的所有数必定在右边集合所有数的左边,然后左边集合求异或值,右边集合求AND值,要求是2个集合的值要一样,求所有集合数。

题解说是简单题。。当时想了好久都没想出来。。。

方法就是开2个二维数组,分别保存从前往后的到第i个所能获得所有的j值,以及从后往前到第i个所能获得的所有的j值,然后最后计算的时候只需要2层循环遍历一遍n和1024,不能简单的2者相乘,因为这样必定会出现重复的集合,正确的做法是要用选择第i个所能到达的j值的个数乘上后面所有能到达j值的个数,那么前者就是dp[i][j] - dp[i-1][j]。切记!做的时候记得要把前面写的加上MOD再去取模,不然可能会出现负数。血的教训。。

AC代码:

#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<stack>#include<cmath>#include<queue>#include<set>#include<ctime>using namespace std;#define ll __int64#define MOD 1000000007ll x[1005][1030],y[1005][1030];int a[1005];int main(){    //freopen("input.txt","r",stdin);    int i,j,t,n;    scanf("%d",&t);    while(t--)    {        memset(x,0,sizeof(x));        memset(y,0,sizeof(y));        scanf("%d",&n);        for(i = 1; i <= n; i++) scanf("%d",&a[i]);        for(i = 1; i <= n; i++)        {            x[i][a[i]]++;            for(j = 0; j < 1024; j++) if(x[i-1][j])            {                x[i][j] += x[i-1][j];                x[i][j] %= MOD;                x[i][j^a[i]] += x[i-1][j];                x[i][j^a[i]] %= MOD;            }        }        for(i = n; i >= 1; i--)        {            y[i][a[i]]++;            for(j = 0; j < 1024; j++) if(y[i+1][j])            {                y[i][j] += y[i+1][j];                y[i][j] %= MOD;                y[i][j&a[i]] += y[i+1][j];                y[i][j&a[i]] %= MOD;            }        }        ll ans = 0;        for(i = 1; i < n; i++)            for(j = 0; j < 1024; j++)                ans = (((x[i][j]-x[i-1][j]+MOD)%MOD*y[i+1][j])%MOD+ans)%MOD;        printf("%I64d\n",ans);    }    return 0;}


0 0
原创粉丝点击