hdu 4901 The Romantic Hero (dp)

题目链接

题意:给一个数组a,从中选择一些元素,构成两个数组s, t,使s数组里的所有元素异或

等于 t数组里的所有元素 位于,求有多少种构成方式。要求s数组里 的所有的元素的下标

小于 t数组里的所有的元素的下标。

分析:比赛的时候,刚开始脑子很乱,后来想了一下思路也敲了,发现自己的程序结果不对

自己一点一点计算后发现自己的程序有一部分计算重复了,其实还是dp的思路不够清晰。

d[i][j]代表第i个数 新产生的结果为数字 j 的个数。

AC代码:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <set>
 7 #include <vector>
 8 #include <algorithm>
 9 #define LL long long
10 const int maxn = 1000+50;
11 const int mo = 1000000000+7;
12 using namespace std;
13 __int64 cnt;
14 int n, a[maxn];
15 __int64 d[maxn][maxn], dt[maxn][maxn], temp[maxn][maxn];
16 
17 int main()
18 {
19     int T, i, j, x;
20     scanf("%d", &T);
21     while(T--)
22     {
23         cnt = 0;
24         memset(d, 0, sizeof(d));
25         memset(dt, 0, sizeof(dt));
26         memset(temp, 0, sizeof(temp));
27         scanf("%d", &n);
28         for(i = 0; i < n; i++)
29         scanf("%d", &a[i]);
30         for(i = 0; i < n; i++)
31         {
32             for(j = 0; j < 1025; j++)
33             {
34                 if(i!=0 && temp[i-1][j])  //让之前存在的和a[i]异或会产生新的存放在d数组里
35                 {
36                     x = (a[i]^j);    //x有可能会大于j,所以不能用d数组直接累加
37                     d[i][x] += temp[i-1][j];
38                 }
39                 d[i][j] %= mo;  //随时取余很重要,不然会wa
40             }
41             d[i][a[i]] ++;  //加上自身
42             for(j = 0; j < 1025; j++)
43             {
44                 if(i != 0)
45             temp[i][j] += temp[i-1][j] + d[i][j];  //temp数组用来维护目前所有的
46             else                                   //结果,并且不可以用d直接加,否则会重复
47             temp[i][j] = d[i][j];
48             temp[i][j] %= mo;
49             }
50         }
51         memset(temp, 0, sizeof(temp));
52         for(i = n-1; i >= 0; i--)
53         {
54             for(j = 0; j < 1025; j++)
55             {
56                 if(temp[i+1][j])
57                 {
58                     x = (a[i]&j);
59                     dt[i][x] += temp[i+1][j];
60                 }
61                 dt[i][j] %= mo;
62             }
63             dt[i][a[i]] ++;
64             for(j = 0; j < 1025; j++)
65             {
66                 temp[i][j] += temp[i+1][j] + dt[i][j];
67                 temp[i][j] %= mo;
68             }
69         }
70         for(i = n-2; i >= 0; i--)
71         for(j = 0; j < 1025; j++)
72         {
73             dt[i][j] += dt[i+1][j];  //这是防止重复的,让dt数组累加,d数组不累加。
74             dt[i][j] %= mo;
75         }
76 
77         for(i = 0; i < n-1; i++)
78             for(j = 0; j < 1025; j++)
79             {
80                 cnt += d[i][j]*dt[i+1][j];  //用前面的乘以后面的
81                 cnt %= mo;
82             }
83         cnt %= mo;
84         printf("%I64d\n", cnt);
85     }
86     return 0;
87 }

 

顺便贴一下自己在比赛中wa的代码,思路不清。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <set>
 7 #include <vector>
 8 #include <algorithm>
 9 #define LL long long
10 const int maxn = 1000+50;
11 const int mo = 1000000000+7;
12 using namespace std;
13 __int64 cnt, f[maxn];
14 int n, a[maxn];
15 __int64 d[maxn][maxn], dt[maxn][maxn];
16 
17 int main()
18 {
19     int T, i, j, tmp;
20     scanf("%d", &T);
21     while(T--)
22     {
23         cnt = 0;
24         memset(d, 0, sizeof(d));
25         memset(dt, 0, sizeof(dt));
26         memset(a, 0, sizeof(a));
27         memset(f, 0, sizeof(f));
28         scanf("%d", &n);
29         for(i = 0; i < n; i++)
30             scanf("%d", &a[i]);
31         d[0][a[0]] = 1;
32         f[a[0]] = 1;
33         for(i = 1; i < n; i++)
34         {
35             for(j = 0; j < 1025; j++)
36             {
37                 if(f[j])
38                 {
39                     tmp = (a[i]^j);
40                     d[i][tmp] += f[j];
41                 }
42                 d[i][j] %= mo;
43             }
44             d[i][a[i]] ++;
45             f[a[i]] ++;
46         }
47 
48         memset(f, 0, sizeof(f));
49         dt[n-1][a[n-1]] = 1;
50         f[a[n-1]] = 1;
51         for(i = n-2; i >= 0; i--)
52         {
53             for(j = 0; j < 1025; j++)
54             {
55                 if(f[j])
56                 {
57                     tmp = (a[i]&j);
58                     dt[i][tmp] += f[j];
59                 }
60                 d[i][j] %= mo;
61             }
62             dt[i][a[i]] ++;
63             f[a[i]] ++;
64         }
65 
66         for(i = n-2; i >= 0; i--)
67         for(j = 0; j < 1025; j++)
68         {
69             dt[i][j] += dt[i+1][j];
70             dt[i][j] %= mo;
71         }
72 
73         for(i = 0; i < n-1; i++)
74             for(j = 0; j < 1025; j++)
75             {
76                 cnt += d[i][j]*dt[i+1][j];
77                 cnt %= mo;
78             }
79         cnt %= mo;
80         printf("%I64d\n", cnt);
81     }
82     return 0;
83 }

 

posted @ 2014-08-01 11:07  水门  阅读(223)  评论(0编辑  收藏  举报