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 }