有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
第一行一个正整数n,表示数的个数。n<=3000
第二行n个正整数a1,a2,...an
Output
最大的和
Sample Input 53 4 5 6 7二分图最小割模型中,
考虑这样一个图
求它的最小割。
对于A-C-E-F来说,
A-C,C-E,E-F中至少要割一条边,
如果让C-E的流量为inf
那么C-E就不可能被割,
所以就是A-C,E-F中至少割一条
即是:A-C,E-F不可共存!
那么我们再来看这个题。
两个数不可以同时选。
就相当于两条边你至少割一条,
割边的流量即是你失去的流量,要失去的流量最小,保留下的最大,只需求最小割。
然而这个图是二分图吗?
显然是,奇偶的二分图
ACcode:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define sqr(a) a*a
#define maxn 3005
#define maxm 1500*1500*2
#define inf 0x3f3f3f3f
#define LL long long
using namespace std;
int n,a[maxn];
int info[maxn],to[maxm],Prev[maxm],cap[maxm],cnt_e=1;
inline void Node(int u,int v,int c)
{
Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v;
cap[cnt_e]=c;
}
inline void Line(int u,int v,int c)
{
Node(u,v,c),Node(v,u,0);
}
int S,T,tmp,flag,stm,vd[maxn],d[maxn];
int aug(int now,int Max)
{
if(now==T)
return Max;
int inc,st=Max,Min=S;
for(int i=info[now];i && st && !flag;i=Prev[i])
if(cap[i])
{
if(d[to[i]]+1==d[now])
{
inc=aug(to[i],min(st,cap[i]));
st-=inc,cap[i]-=inc,cap[i^1]+=inc;
}
Min=min(Min,d[to[i]]);
}
if(Max==st)
{
!(--vd[d[now]]) && (flag=1);
vd[d[now]=Min+1]++;
}
return Max-st;
}
int sap()
{
memset(d,0,sizeof d);
memset(vd,0,sizeof vd);
vd[0]=T;
for(stm=flag=0;!flag;) stm+=aug(S,inf);
return stm;
}
int gcd(int a,int b)
{
return !b?a:gcd(b,a%b);
}
int main()
{
int sum=0;
scanf("%d",&n);
S=n+1,T=n+2;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]&1) Line(S,i,a[i]);
else Line(i,T,a[i]);
sum+=a[i];
}
for(int i=1;i<=n;i++) if(a[i]&1)
for(int j=1;j<=n;j++) if(!(a[j]&1))
if(gcd(a[i],a[j])==1 && abs(sqr(floor(sqrt(1.0*a[i]*a[i]+1.0*a[j]*a[j])))-1.0*a[i]*a[i]-1.0*a[j]*a[j])<=1e-5)
Line(i,j,inf);
printf("%d\n",sum-sap());
}