BZOJ 3275: Number

3275: Number

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 874  Solved: 371
[Submit][Status][Discuss]

Description

有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1

Input

第一行一个正整数n,表示数的个数。
第二行n个正整数a1,a2,?an。
 
 

Output

最大的和。
 

Sample Input

5
3 4 5 6 7



Sample Output

22


HINT

 

n<=3000。

 

Source

[Submit][Status][Discuss]

 

机制建图,同 BZOJ 3158: 千钧一发

 

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 typedef long long lnt;
  6 
  7 const int siz = 1000005;
  8 const int inf = 1000000007;
  9 
 10 int n;
 11 int a[siz];
 12 int b[siz];
 13 
 14 int tot;
 15 int s, t;
 16 int hd[siz];
 17 int to[siz];
 18 int fl[siz];
 19 int nt[siz];
 20 
 21 inline void add(int u, int v, int f)
 22 {
 23     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
 24     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++;
 25 }
 26 
 27 int dep[siz];
 28 
 29 inline bool bfs(void)
 30 {
 31     static int que[siz];
 32     static int head, tail;
 33 
 34     memset(dep, 0, sizeof(dep));
 35     head = 0, tail = 0;
 36     que[tail++] = s;
 37     dep[s] = 1;
 38 
 39     while (head != tail)
 40     {
 41         int u = que[head++], v;
 42 
 43         for (int i = hd[u]; ~i; i = nt[i])
 44             if (!dep[v = to[i]] && fl[i])
 45                 dep[que[tail++] = v] = dep[u] + 1;
 46     }
 47 
 48     return dep[t];
 49 }
 50 
 51 int cur[siz];
 52 
 53 int min(int a, int b)
 54 {
 55     return a < b ? a : b;
 56 }
 57 
 58 int dfs(int u, int f)
 59 {
 60     if (u == t || !f)
 61         return f;
 62         
 63     int used = 0, flow, v;
 64 
 65     for (int i = cur[u]; ~i; i = nt[i])
 66         if (dep[v = to[i]] == dep[u] + 1 && fl[i])
 67         {
 68             flow = dfs(v, min(f - used, fl[i]));
 69             
 70             used += flow;
 71             fl[i] -= flow;
 72             fl[i^1] += flow;
 73 
 74             if (used == f)
 75                 return f;
 76 
 77             if (fl[i])
 78                 cur[u] = i;
 79         }
 80 
 81     if (!used)
 82         dep[u] = 0;
 83 
 84     return used;
 85 }
 86 
 87 inline int maxFlow(void)
 88 {
 89     int maxFlow = 0, newFlow;
 90 
 91     while (bfs())
 92     {
 93         for (int i = s; i <= t; ++i)
 94             cur[i] = hd[i];
 95 
 96         while (newFlow = dfs(s, inf))
 97             maxFlow += newFlow;
 98     }
 99 
100     return maxFlow;
101 }
102 
103 inline lnt sqr(lnt x)
104 {
105     return x * x;
106 }
107 
108 int gcd(int x, int y)
109 {
110     return y ? gcd(y, x % y) : x;
111 }
112 
113 inline bool check(int x, int y)
114 {
115     if (gcd(x, y) != 1)
116         return false;
117 
118     lnt t = sqr(x) + sqr(y);
119     if (sqr(sqrt(t)) != t)
120         return false;
121 
122     return true;
123 }
124 
125 signed main(void)
126 {
127     scanf("%d", &n);
128 
129     for (int i = 1; i <= n; ++i)
130         scanf("%d", a + i);
131 
132     for (int i = 1; i <= n; ++i)
133         b[i] = a[i];
134     
135     s = 0, t = n + 1;
136 
137     memset(hd, -1, sizeof(hd));
138 
139     for (int i = 1; i <= n; ++i)
140         if (a[i] & 1)
141             add(s, i, b[i]);
142         else
143             add(i, t, b[i]);
144 
145     for (int i = 1; i <= n; ++i)
146         for (int j = 1; j <= n; ++j)
147             if (a[i] & 1)if (!(a[j] & 1))
148                 if (check(a[i], a[j]))
149                     add(i, j, inf);
150 
151     int sum = 0;
152 
153     for (int i = 1; i <= n; ++i)
154         sum += b[i];
155 
156     printf("%d\n", sum - maxFlow());
157 }

 

@Author: YouSiki

posted @ 2017-01-04 19:57  YouSiki  阅读(144)  评论(0编辑  收藏  举报