题目描述

有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

输出

最大的和

样例输入

5
3 4 5 6 7

样例输出

22
 
可以发现如果两个数都是偶数,那么$gcd>=2$,一定可以同时选;如果两个数都是奇数,那么两个数的平方和是$4$的倍数加$2$,而一个奇数的平方是$4$的倍数加$1$,一个偶数的平方是$4$的倍数,所以两个奇数一定可以同时选。那么我们可以将奇数与源点相连,将偶数与汇点相连,然后枚举任意一对奇偶不同的数,如果不能同时选就在两点之间连边。答案就是所有数之和$-$最小割。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
int head[4000];
int to[3000000];
int next[3000000];
int val[3000000];
int d[4000];
int q[4000];
int back[4000];
int S,T;
int x,y,k;
int n,m;
int tot=1;
int ans;
int a[4000];
void add(int x,int y,int v)
{
tot++;
next[tot]=back[x];
back[x]=tot;
to[tot]=y;
val[tot]=v;
tot++;
next[tot]=back[y];
back[y]=tot;
to[tot]=x;
val[tot]=0;
}
bool bfs(int S,int T)
{
int r=0;
int l=0;
memset(d,-1,sizeof(d));
q[r++]=T;
d[T]=2;
while(l<r)
{
int now=q[l];
for(int i=back[now];i;i=next[i])
{
if(d[to[i]]==-1&&val[i^1]!=0)
{
d[to[i]]=d[now]+1;
q[r++]=to[i];
}
}
l++;
}
if(d[S]==-1)
{
return false;
}
else
{
return true;
}
}
int dfs(int x,int flow)
{
if(x==T)
{
return flow;
}
int now_flow;
int used=0;
for(int &i=head[x];i;i=next[i])
{
if(d[to[i]]==d[x]-1&&val[i]!=0)
{
now_flow=dfs(to[i],min(flow-used,val[i]));
val[i]-=now_flow;
val[i^1]+=now_flow;
used+=now_flow;
if(now_flow==flow)
{
return flow;
}
}
}
if(used==0)
{
d[x]=-1;
}
return used;
}
int dinic()
{
int res=0;
while(bfs(S,T))
{
memcpy(head,back,sizeof(back));
res+=dfs(S,0x3f3f3f3f);
}
return res;
}
int gcd(int x,int y)
{
return y==0?x:gcd(y,x%y);
}
ll get(ll x)
{
return 1ll*x*x;
}
bool check(int x,int y)
{
if(gcd(x,y)!=1)
{
return false;
}
ll c=1ll*x*x+1ll*y*y;
if(get(sqrt(c))!=c)
{
return false;
}
return true;
}
int main()
{
scanf("%d",&n);
S=n+1;
T=S+1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
ans+=a[i];
if(a[i]&1)
{
add(S,i,a[i]);
}
else
{
add(i,T,a[i]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(check(a[i],a[j]))
{
if(a[i]&1)
{
add(i,j,INF);
}
else
{
add(j,i,INF);
}
}
}
}
printf("%d",ans-dinic());
}

最新文章

  1. 最新官方WIN10系统32位,64位系统ghost版下载
  2. myeclicps开发web时候复制一个工程改名字后执行出现404错误
  3. Accelerating Matlab
  4. c语言结构体3之结构体嵌套
  5. MySQL学习分享--&gt;查询--&gt;查询的分类
  6. phpmyadmin设置密码,不用登录直接进入
  7. 调试 smallcorgi/Faster-RCNN_TF 的demo过程遇到的问题
  8. 聊聊javaMail
  9. Servlet 易错点和注意点
  10. Flutter控制屏幕旋转
  11. vnc server的安装
  12. python——虚拟环境之pipenv的安装及使用(windows10,64位)
  13. esp8266(3) Arduino通过ESP8266连接和获取网站源代码
  14. Python3学习之路~5.1 模块介绍
  15. 让shell脚本中的echo输出带颜色
  16. Winform 实现无边框窗体移动功能
  17. 尚硅谷springboot学习10-@PropertySource,@ImportResource,@Bean
  18. 纠结好久的VM虚拟机MAC地址绑定问题
  19. SQL 参考
  20. Hibernate 查询说明

热门文章

  1. 安卓权限申请处理框架Android-UsesPermission
  2. mybatis源码- 反射模块一(跟着MyBatis学反射):类级别信息的封装
  3. 网络应用简记(4):DNS使用
  4. tkinter python(图形开发界面)
  5. CentOS 6 升级 curl
  6. Method not found: !!0[] System.Array.Empty()错误
  7. HDU - 1540 线段树的合并
  8. JSP页面的基本元素
  9. 学习memcache
  10. PAT L2-024 部落