bzoj3275: Number

3275: Number

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 892  Solved: 383
[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。

题解

首先观察出可以把数字按奇数和偶数变成二分图,因为第一条性质保证了奇数和奇数之间没有边(奇数的平方和模4余2,而是偶数的平方数是4的倍数),第二条性质保证了偶数和偶数之间没有边。然后把奇数连s,偶数连T,容量是权值;奇数和偶数之间满足条件就连容量无穷打的边。这样最后答案要保证选出来的点组成的子图中S到T不连通,所以割某条边就相当于这个数不在集合里,最大化选的点的圈就是最小化割的权。最后所有点的权和减去最小割就行。

  1 program j01;
  2 const maxn=3006;maxm=1000086;
  3 var flow,next,q:array[0..maxm]of longint;
  4     head:array[0..maxn]of longint;
  5     dis,l,a:array[0..maxn]of longint;
  6     s,t,tt,n,i,j:longint;
  7     ans:int64;
  8 
  9 procedure add(u,v,w:longint);
 10 begin
 11   inc(tt);q[tt]:=v;next[tt]:=head[u];head[u]:=tt;flow[tt]:=w;
 12 end;
 13 
 14 function min(a,b:longint):longint;
 15 begin
 16   if a<b then exit(a) else exit(b);
 17 end;
 18 
 19 function gcd(a,b:longint):longint;
 20 begin
 21   if b=0 then exit(a) else exit(gcd(b,a mod b));
 22 end;
 23 
 24 function jud(a,b:int64):boolean;
 25 var tmp,m:int64;
 26 begin
 27   tmp:=a*a+b*b;
 28   m:=trunc(sqrt(tmp));
 29   exit(m*m=tmp);
 30 end;
 31 
 32 function bfs:boolean;
 33 var h,tail,i,j:longint;
 34 begin
 35   h:=0;tail:=1;l[1]:=s;
 36   fillchar(dis,sizeof(dis),$3f);dis[s]:=0;
 37   while h<>tail do
 38   begin
 39     inc(h);i:=l[h];j:=head[i];
 40     while j>0 do
 41     begin
 42       if (dis[i]+1<dis[q[j]])and(flow[j]>0) then
 43       begin
 44         dis[q[j]]:=dis[i]+1;
 45         inc(tail);l[tail]:=q[j];
 46       end;
 47       j:=next[j];
 48     end;
 49   end;
 50   if dis[t]=$3f3f3f3f then exit(false) else exit(true);
 51 end;
 52 
 53 function dfs(i,ll:longint):longint;
 54 var j,x,tmp:longint;
 55 begin
 56   if i=t then exit(ll);
 57   j:=head[i];x:=0;
 58   while j>0 do
 59   begin
 60     if (dis[q[j]]=dis[i]+1)and(flow[j]>0) then
 61     begin
 62       tmp:=dfs(q[j],min(ll-x,flow[j]));
 63       dec(flow[j],tmp);
 64       inc(flow[j xor 1],tmp);
 65       inc(x,tmp);
 66       if x=ll then exit(x);
 67     end;
 68     j:=next[j];
 69   end;
 70   if x=0 then dis[i]:=-1;
 71   exit(x);
 72 end;
 73 
 74 begin
 75   readln(n);
 76   s:=0;t:=n+1;tt:=1;ans:=0;
 77   for i:=1 to n do
 78   begin
 79     read(a[i]);ans:=ans+a[i];
 80     if a[i] mod 2=1 then
 81     begin
 82       add(s,i,a[i]);add(i,s,0);
 83     end else
 84     begin
 85       add(i,t,a[i]);add(t,i,0);
 86     end;
 87   end;
 88   for i:=1 to n do
 89     if a[i] mod 2=1 then
 90       for j:=1 to n do
 91         if a[j] mod 2=0 then
 92           if (gcd(a[i],a[j])=1)and jud(a[i],a[j]) then
 93           begin
 94             add(i,j,maxlongint);
 95             add(j,i,0);
 96           end;
 97   while bfs do
 98     ans:=ans-dfs(s,maxlongint);
 99   writeln(ans);
100 end.
View Code

 

posted @ 2017-02-16 00:02  OldJang  阅读(429)  评论(0编辑  收藏  举报