有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。
第一行一个正整数N。
第二行共包括N个正整数,第 个正整数表示Ai。
第三行共包括N个正整数,第 个正整数表示Bi。
共一行,包括一个正整数,表示在合法的选择条件下,可以获得的能量值总和的最大值。
1<=N<=1000,1<=Ai,Bi<=10^6
一开始没仔细读题,看成同时满足两个,WA了几波后才发现看错了...
对奇数偶数讨论一下,奇数之间肯定满足1.偶数之间肯定满足2
最小割就好
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();} while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int Gcd(int a,int b) { if (b==0) return a; else return Gcd(b,a%b); } bool check(long long a,long long b) { if (Gcd(a,b)>1) return true; long long T=sqrt(a*a+b*b); if (T*T!=a*a+b*b) return true; return false; } #define maxn 5000 #define maxm 1000010 int N,A[maxn],B[maxn],tot; struct Edgenode{int next,to,cap;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w) { cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w; } void insert(int u,int v,int w) {add(u,v,w); add(v,u,0);} int cur[maxn],dis[maxn],S,T; bool bfs() { queue<int> q; memset(dis,-1,sizeof(dis)); q.push(S); dis[S]=0; while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==-1) dis[edge[i].to]=dis[now]+1,q.push(edge[i].to); } return dis[T]!=-1; } int dfs(int loc,int low) { if (loc==T) return low; int w,used=0; for (int i=cur[loc]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==dis[loc]+1) { w=dfs(edge[i].to,min(low-used,edge[i].cap)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (edge[i].cap) cur[loc]=i; if (used==low) return low; } if (!used) dis[loc]=-1; return used; } #define inf 0x7fffffff int dinic() { int tmp=0; while (bfs()) { for (int i=S; i<=T; i++) cur[i]=head[i]; tmp+=dfs(S,inf); } return tmp; } void Build() { S=0,T=N+1; for (int i=1; i<=N; i++) if ((A[i]%2)) insert(S,i,A[i]); else insert(i,T,A[i]); for (int i=1; i<=N; i++) for (int j=1; j<=N; j++) if ((A[i]%2) && !(A[j]%2) && !check(A[i],A[j])) insert(i,j,inf); } int main() { N=read(); for (int i=1; i<=N; i++) A[i]=read(),tot+=A[i]; //for (int i=1; i<=N; i++) B[i]=read(),tot+=B[i]; Build(); int maxflow=dinic(); printf("%d\n",tot-maxflow); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();} while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int Gcd(int a,int b) { if (b==0) return a; else return Gcd(b,a%b); } bool check(long long a,long long b) { if (Gcd(a,b)>1) return true; long long T=sqrt(a*a+b*b); if (T*T!=a*a+b*b) return true; return false; } #define maxn 3000 #define maxm 1000010 int N,A[maxn],B[maxn],tot; struct Edgenode{int next,to,cap;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w) { cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w; } void insert(int u,int v,int w) {add(u,v,w); add(v,u,0);} int cur[maxn],dis[maxn],S,T; bool bfs() { queue<int> q; memset(dis,-1,sizeof(dis)); q.push(S); dis[S]=0; while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==-1) dis[edge[i].to]=dis[now]+1,q.push(edge[i].to); } return dis[T]!=-1; } int dfs(int loc,int low) { if (loc==T) return low; int w,used=0; for (int i=cur[loc]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==dis[loc]+1) { w=dfs(edge[i].to,min(low-used,edge[i].cap)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (edge[i].cap) cur[loc]=i; if (used==low) return low; } if (!used) dis[loc]=-1; return used; } #define inf 0x7fffffff int dinic() { int tmp=0; while (bfs()) { for (int i=S; i<=T; i++) cur[i]=head[i]; tmp+=dfs(S,inf); } return tmp; } void Build() { S=0,T=N+1; for (int i=1; i<=N; i++) if ((A[i]%2)) insert(S,i,B[i]); else insert(i,T,B[i]); for (int i=1; i<=N; i++) for (int j=1; j<=N; j++) if ((A[i]%2) && !(A[j]%2) && !check(A[i],A[j])) insert(i,j,inf); } int main() { N=read(); for (int i=1; i<=N; i++) A[i]=read(); for (int i=1; i<=N; i++) B[i]=read(),tot+=B[i]; Build(); int maxflow=dinic(); printf("%d\n",tot-maxflow); return 0; }
【BZOJ-3275&3158】Number&千钧一发 最小割
标签:
原文地址:http://www.cnblogs.com/DaD3zZ-Beyonder/p/5469721.html