有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
n<=3000。
网络流
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #define N 3003 #define M 3000003 using namespace std; int n,m,tot=-1; int a[N],p[N],sum; int next[M*2],point[M],v[M*2],remain[M*2]; int deep[M],num[M],cur[M],laste[M],maxflow; const int inf=1e9; void add(int x,int y,int z) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; } bool bfs1(int s,int t) { memset(deep,0x7f,sizeof(deep)); for (int i=s;i<=t;i++) cur[i]=point[i]; deep[s]=0; queue<int> p; p.push(s); while(!p.empty()) { int now=p.front(); p.pop(); for (int i=point[now];i!=-1;i=next[i]) if (deep[v[i]]>inf&&remain[i]) deep[v[i]]=deep[now]+1,p.push(v[i]); } if (deep[t]>inf) return false; return true; } int dfs(int now,int t,int limit) { if (now==t||!limit) return limit; int flow=0,f; for(int i=cur[now];i!=-1;i=next[i]) { cur[now]=i; if (remain[i]>0&&deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(limit,remain[i])))) { flow+=f; limit-=f; remain[i]-=f; remain[i^1]+=f; if (!limit) break; } } return flow; } int dinic(int s,int t) { int ans=0; while (bfs1(s,t)) ans+=dfs(s,t,inf); return ans; } int gcd(int x,int y) { int r; while (y!=0) { r=x%y; x=y; y=r; } return x; } bool pd(int x,int y) { int t=x*x+y*y; int k=sqrt(t); if (k*k==t) return false; return true; } int main() { scanf("%d",&n); memset(point,-1,sizeof(point)); memset(next,-1,sizeof(next)); for (int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i]; //cout<<sum<<endl; for (int i=1;i<=n;i++) add(0,i,a[i]); for (int i=1;i<=n;i++) add(i+n,2*n+1,a[i]); for (int i=1;i<=n-1;i++) for (int j=i+1;j<=n;j++) if (gcd(a[i],a[j])==1&&!pd(a[i],a[j])) add(i,j+n,inf),add(j,i+n,inf); int l=dinic(0,2*n+1); printf("%d\n",sum-l/2); }