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

时间: 2024-10-19 03:45:23

BZOJ 3275: Number的相关文章

BZOJ 3275: Number( 最小割 )

--------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 3009; const int INF = 0x7FFFFFFF; struct edge { int to, cap; edge *next, *rev; } E[1000000], *p

BZOJ 3275 Number &amp;&amp; 3158 千钧一发 最小割

题目大意:给出一些数字,要求选出一些数字并保证所有数字和最大,要求这其中的数字任意两个至少满足一个条件,则不能同时被选:1.这两个数的平方和是完全平方数.2.gcd(a,b) = 1. 思路:我们可以将奇数和偶数分开来讨论,奇数不满足1,偶数不满足2,所以奇数和奇数,偶数和偶数不会互相影响.之后O(n^2)的讨论其他数字对,有影响就连边,流量正无穷,最后跑最小割最最大获利. CODE: #define _CRT_SECURE_NO_WARNINGS #include <cmath> #incl

bzoj 3858: Number Transformation

3858: Number Transformation Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 82  Solved: 41[Submit][Status] Description Teacher Mai has an integer x. He does the following operations k times. In the i-th operation, x becomes the least integer no less th

bzoj 3275 最小割

给你一堆东西,叫你选一些东西出来,使得价值最大,要求选出的东西集合中的任意a,b满足性质p. 可以考虑: 1.拟阵? 2.二分图? 这道题由于数学硬伤,不知道不存在两条直角边是奇数,斜边是整数的直角三角形. 证明是: 对于奇数a: a*a = 1 mod 4 对于偶数a: a*a = 0 mod 4 所以对于两个奇数a,b: a*a+b*b = 2 mod 4 不存在整数c使得: a*a+b*b = c*c mod 4 1 /***********************************

BZOJ 1114 Number theory(莫比乌斯反演+预处理)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=71738 题意:给你一个整数序列a1, a2, a3, ... , an.求gcd(ai, aj) = 1 且 i < j的对数. 思路:利用莫比乌斯反演很快就能得到公式,但是求解时我们要知道序列中1, 2, 3, ... , max(a1, a2, ... , an)的倍数各是多少.我们用num[i]=k,来表示序列中有k个数是i的倍数,那么这部分对结果的影响是m

BZOJ 3858 Number Transformation 数论

题目大意:给定n,k,i从1到k循环一遍,每次将n更新成i的倍数中第一个大于等于n的 求最终的n 逗比题... 我们会发现当i>=sqrt(n)时,ceil(n/i)每次都是一样的- - ↑不能理解这句话的注意n是变化的 于是当i>=sqrt(n)时只需要输出ceil(n/i)*k即可 别的做法基本都卡了- - #include <cstdio> #include <cstring> #include <iostream> #include <algo

最小割 专题练习

最小割的建模技巧 技巧0. INF 的使用 (u, v, INF) . 这条边不能割, u 和 v 的状态必须一样. 技巧1. 核心模型 若 x, y 不同, 则减少 v . 连双向边 (x, y, v) . 技巧2. 统治点 x 与集合 A 中一个不同, 则减少 v . a[1] / v / x <------> A ---- a[2] \ \ a[3] 技巧3. 最大 - 最小转化 假装把所有都给取了, 这样条件会取反. 技巧4. A 中的都一样. 建立与 S 一定相连的点 v1, 即 (

【BZOJ】【3275】Numbers

网络流/最小割 Orz了Jiry_2神犇,蒟蒻网络流建模什么的完全不会啊T_T 按奇偶性来分组实在太巧妙了……然后相关的点之间连边表示只能选其一,来求最小割…… 1 /************************************************************** 2 Problem: 3275 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:1252 ms 7 Memory:1708 kb 8 ****

BZOJ3275: Number

1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #i