2012 Multi-University Training Contest 4

  If we have two sorted lists of integers A and B, we can easily find in linear time by keeping two pointers if there are a in A and b in B such that a+b=c (c is given).
  Now, for this problem, we create a sorted list of all sums for S[0] and S[1] (call it M[0]), and a sorted list of all sums for S[2] and S[3] (call it M[1]). We can do this in O(n^2 log n).
  Then, for each member c of S[4], we find if there's a in M[0] and b in M[1] such that a+b+c=0 using the method described in paragraph one. Sinc each search takes O(n^2) time (because the size of lists are O(n^2)), and we have O(n) members in S[4], total time complexity of this algorithm will be O(n^3).

View Code
 1   #include <cstdio>
 2   #include <cstring>
 3   #include <algorithm>
 4   #define N 205
 5   #define LL long long
 6 
 7   LL a[N], b[N], c[N];
 8   LL sum1[N * N], sum2[N * N], m1, m2;
 9   
10   int main()
11   {
12       int t, n, i, j, k;
13       scanf("%d", &t);
14       while(t --)
15       {
16           scanf("%d", &n);
17           for(i = 0; i < n; i ++)
18               scanf("%I64d", &a[i]);
19           for(i = 0; i < n; i ++)
20               scanf("%I64d", &b[i]);
21   
22           m1 = 0;
23           for(i = 0; i < n; i ++)
24               for(j = 0; j < n; j ++)
25                   sum1[m1 ++] = a[i] + b[j];
26           
27           for(i = 0; i < n; i ++)
28               scanf("%I64d", &a[i]);
29           for(i = 0; i < n; i ++)
30               scanf("%I64d", &b[i]);
31           
32           m2 = 0;
33           for(i = 0; i < n; i ++)
34               for(j = 0; j < n; j ++)
35                   sum2[m2 ++] = a[i] + b[j];
36                   
37           for(i = 0; i < n; i ++)
38               scanf("%I64d", &c[i]);
39           
40           std::sort(sum1, sum1 + m1);
41           std::sort(sum2, sum2 + m2);
42           std::sort(c, c + n);
43   
44           bool flag = false;
45           for(i = 0; i < n; i ++)
46           {
47               flag = false;
48               j = 0, k = m2 -1;
49               while(j < m1 && k >= 0)
50               {
51                   LL v = -(sum1[j] + sum2[k]);
52                   if(c[i] == v)
53                   {
54                       flag = true;
55                       break;
56                   }
57                   else if(c[i] < v)
58                       j ++;
59                   else
60                       k --;
61               }
62               if(flag)
63                   break;
64           }
65           if(flag)
66               printf("Yes\n");
67           else
68               printf("No\n");
69       }
70       return 0;
71   }

 

HDOJ 4336 Card Collector

  概率/组合数学 + 容斥原理。设卡片的分布p=(p1,p2,...,pn)。则: 

  

  

  用二进制表示集合枚举实现。

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 const int maxn = 20 + 2;
 4 double p[maxn];
 5 int n, m;
 6 
 7 double solve(int s)
 8 {
 9     double res = 0.0;
10     m = 0;
11     for(int i = 0; i < n; i ++)
12         if(s & (1 << i))
13             res += p[i], m ++;
14     return 1.0 / res; 
15 }
16 
17 int main()
18 {
19     while(scanf("%d", &n) == 1)
20     {
21         for(int i = 0; i < n; i++)
22             scanf("%lf", &p[i]);
23         double ans = 0.0;
24         for(int s = 1; s < (1 << n); s++)
25         {
26             double t = solve(s);
27             ans += t * ((m & 1) ? 1 : -1);
28         }
29         printf("%lf\n", ans);
30     }
31 }

 

 

      AKing...

 

posted @ 2012-08-30 11:54  芒果布丁  阅读(217)  评论(0编辑  收藏  举报