2014多校4的1005
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4901
The Romantic HeroTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 393 Accepted Submission(s): 150 Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse any request from the devil. Also, this devil is looking like a very cute Loli. Input The first line contains an integer T, denoting the number of the test cases. For each test case, the first line contains a integers n. The next line contains n integers a_1,a_2,...,a_n which are separated by a single space. Output For each test case, output the result in one line. Sample Input 2 Sample Output 1 Author WJMZBMR Source 2014 Multi-University Training Contest 4 Recommend We have carefully selected several similar problems for you: 4906 4905 4904 4903 4902 |
题意:
给一列数,让你选两个集合,A集合所有元素下标小于B集合所有元素下标,A集合的所有元素异或等于B集合所有元素AND,两个集合都非空,求集合元素有多少种选法,MOD 10^9+7。0<=元素大小<1024,最多1000个元素。
题解:
DP!(虽然我一开始就想到DP,不过我DP功力太差,比赛中实在做不出,结束后看了http://www.cnblogs.com/avema/p/3881466.html的超快题解(虽然没写题解只有代码)才学会的)
官方题解居然是这样的“水题,大家都会做吧?”我都怕了!虽然很多人过了,好像的确很水的样子……
言归正传,我来讲一下这个DP。
f[i][j]:由0~i的元素异或得到j的种类数。
h[i][j]:由i~n-1的元素AND得到j的种类数。
g[i][j]:由i~n-1的元素,且一定包含i,AND得到j的种类数。
求出这些,最后把f[i][j]*g[i+1][j]求和就得到答案了!
这里用g而不用h,防止重复计数,非常高端。我写的时候也一直在考虑防止重复计数,结果写出来4重循环,我自己都怕,看来是我对DP的理解不够深。这个只用两重循环,快得飞起来。具体实现看代码吧,还算比较简单易懂。
代码:
1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<math.h> 5 6 #define ll __int64 7 #define usint unsigned int 8 #define mz(array) memset(array, 0, sizeof(array)) 9 #define RE freopen("1.in","r",stdin) 10 #define WE freopen("mask.txt","w",stdout) 11 12 #define maxa 1024 13 #define maxn 1000 14 #define C 1000000007 15 16 int f[maxn-1][maxa],g[maxn][maxa],h[maxn][maxa]; 17 18 int main() { 19 20 int a[maxn],T,n; 21 short i,j,t; 22 int ans; 23 scanf("%d",&T); 24 while(T--) { 25 scanf("%d",&n); 26 for(i=0; i<n; i++) 27 scanf("%d",&a[i]); 28 mz(f); 29 mz(g); 30 mz(h); 31 f[0][a[0]]=1; 32 for(i=1; i<n-1; i++) { 33 f[i][a[i]]++;///单独一个元素的集合的情况 34 for(j=0; j<maxa; j++) { 35 if(f[i-1][j]) { 36 f[i][j]+=f[i-1][j];///继承之前算好的情况(就是 不包括当前元素的情况) 37 f[i][j]%=C; 38 t=j^a[i]; 39 f[i][t]+=f[i-1][j];///由前一次的情况异或当前元素得到的情况(包括当前元素的情况) 40 f[i][t]%=C; 41 } 42 43 } 44 } 45 46 g[n-1][a[n-1]]=1; 47 h[n-1][a[n-1]]=1; 48 for(i=n-2; i>0; i--) { 49 g[i][a[i]]++; 50 h[i][a[i]]++; 51 for(j=0; j<maxa; j++) { 52 if(h[i+1][j]) { 53 h[i][j]+=h[i+1][j]; 54 h[i][j]%=C; 55 t=j&a[i]; 56 h[i][t]+=h[i+1][j]; 57 h[i][t]%=C; 58 59 g[i][t]+=h[i+1][j];///包括当前元素的情况(g没有不包括当前元素的情况) 60 g[i][t]%=C; 61 } 62 63 } 64 } 65 ans=0; 66 for(i=0; i<n-1; i++) 67 for(j=0; j<maxa; j++) { 68 if(f[i][j]&&g[i+1][j]) { 69 ans+=(((ll)f[i][j])*(g[i+1][j])%C); 70 ans%=C; 71 } 72 } 73 printf("%d\n",ans); 74 } 75 return 0; 76 }
这次来个C的代码,酷不酷炫(其实没有类都可以换成C的吧
HDU4901 The Romantic Hero 计数DP,布布扣,bubuko.com