有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
标签:
看了师兄的建图方法,然后YY一下懂了一点?=>建图后即是求最小割,也就是说求最少去掉几条边就能使图不连通,图不连通意味着不会有两个相互矛盾的节点存在,若能联通的话会有两个相互矛盾的节点能够同时存在,所以=>("
S->每个奇数,每个偶数->T各连一条边, 容量为这个数字.然后不能同时选的两个数连容量为+oo的边. 总数-最大流即是答案.
因为满足a2+b2=c2的a,b一定是一奇一偶或者两个偶数, 2偶不满足gcd=1, 所以两个数不能同时选一定是一奇一偶.")
以上引自sj师兄。两个奇数证明一下不难得出。
然后又是错了一个地方然后。。还有判断a*a+b*b=c*c不会判断,orz。
---------------------------------------------------------------------------------------
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define ll long long
const int inf=0x3f3f3f3f;
int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){
if(c==‘-‘) f=-1;
c=getchar();
}
while(isdigit(c)){
x=x*10+c-‘0‘;
c=getchar();
}
return x*f;
}
struct edge{
int to,cap;
edge *next,*rev;
};
edge e[400000],*cur[3005],*head[3005],*p[3005],*pt;
int d[3005],cnt[3005],a[3005];
void add(int u,int v,int d){
pt->to=v;
pt->cap=d;
pt->next=head[u];
head[u]=pt++;
}
void adde(int u,int v,int d){
add(u,v,d);add(v,u,0);
head[u]->rev=head[v];
head[v]->rev=head[u];
}
int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
bool pd(int x,int y){
if(gcd(x,y)!=1) return false;
ll tmp=(ll)x*x+(ll)y*y;
ll t=sqrt(tmp);
if(tmp==t*t) return true;
return false;
}
int maxflow(int s,int t,int n){
int flow=0,a=inf,x=s;
clr(cnt,0);
clr(d,0);cnt[0]=n;
while(d[s]<n){
edge *ee;
for(ee=cur[x];ee;ee=ee->next){
if(ee->cap>0&&d[ee->to]==d[x]-1)
break;
}
if(ee){
a=min(a,ee->cap);
cur[x]=p[ee->to]=ee;
x=ee->to;
if(x==t){
while(x!=s){
p[x]->cap-=a;
p[x]->rev->cap+=a;
x=p[x]->rev->to;
}
flow+=a;
a=inf;
}
}
else{
if(--cnt[d[x]]==0) break; //又是这里又是这里
d[x]=n;
for(ee=head[x];ee;ee=ee->next){
if(ee->cap>0&&d[ee->to]+1<d[x]){
d[x]=d[ee->to]+1;
cur[x]=ee;
}
}
cnt[d[x]]++;
if(x!=s) x=p[x]->rev->to;
}
}
return flow;
}
int main(){
int n=read(),s=0,t=n+1,tot=t+1,ans=0;
pt=e;
rep(i,n){
a[i]=read();ans+=a[i];
a[i]%2?adde(s,i,a[i]):adde(i,t,a[i]);
}
rep(i,n)
if(a[i]%2)
rep(j,n)
if(a[j]%2==0&&pd(a[i],a[j]))
adde(i,j,inf);
printf("%d\n",ans-maxflow(s,t,tot));
return 0;
}
---------------------------------------------------------------------------------------
有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
n<=3000。
标签:
原文地址:http://www.cnblogs.com/fighting-to-the-end/p/5125437.html