bzoj 3275: Number
3275: Number
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1259 Solved: 534
[Submit][Status][Discuss]
Description
有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
Input
第一行一个正整数n,表示数的个数。n<=3000
第二行n个正整数a1,a2,...an
Output
最大的和
Sample Input
5
3 4 5 6 7
3 4 5 6 7
Sample Output
22
总感觉以前做过2333
因为奇数和奇数的平方和不可能是完全平方数(考虑用(2*n+1)表示奇数,展开之后发现平方和是个偶数却%4余2,所以肯定不是完全平方数),而偶数和偶数的
gcd至少是2。
所以可以发现不满足条件的一定是一奇一偶,然后这题就是个二分图最大独立集了233
#include<bits/stdc++.h> #define ll long long #define maxn 3005 #define pb push_back using namespace std; const int inf=1<<30; vector<int> g[maxn]; struct lines{ int to,flow,cap; }l[maxn*1000]; int S,T,t=-1,d[maxn],cur[maxn]; bool v[maxn]; inline void add(int from,int to,int cap){ l[++t]=(lines){to,0,cap},g[from].pb(t); l[++t]=(lines){from,0,0},g[to].pb(t); } inline bool BFS(){ memset(v,0,sizeof(v)); queue<int> q; q.push(S),v[S]=1,d[S]=0; int x; lines e; while(!q.empty()){ x=q.front(),q.pop(); for(int i=g[x].size()-1;i>=0;i--){ e=l[g[x][i]]; if(e.flow<e.cap&&!v[e.to]){ v[e.to]=1,d[e.to]=d[x]+1; q.push(e.to); } } } return v[T]; } int dfs(int x,int a){ if(!a||x==T) return a; int flow=0,f,sz=g[x].size(); for(int &i=cur[x];i<sz;i++){ lines &e=l[g[x][i]]; if(d[e.to]==d[x]+1&&(f=dfs(e.to,min(a,e.cap-e.flow)))){ a-=f,flow+=f; e.flow+=f,l[g[x][i]^1].flow-=f; if(!a) break; } } return flow; } inline int max_flow(){ int an=0; while(BFS()){ memset(cur,0,sizeof(cur)); an+=dfs(S,inf); } return an; } int n,a[maxn]; int tot=0; int gcd(int x,int y){ return y?gcd(y,x%y):x; } inline bool can(int x,int y){ ll now=x*(ll)x+y*(ll)y,O=sqrt(now); return O*O==now&&gcd(x,y)==1; } int main(){ scanf("%d",&n),S=0,T=n+1; for(int i=1;i<=n;i++) scanf("%d",a+i),tot+=(ll)a[i]; for(int i=1;i<=n;i++) if(a[i]&1){ add(S,i,a[i]); for(int j=1;j<=n;j++) if(!(a[j]&1)&&can(a[i],a[j])) add(i,j,inf); } else add(i,T,a[i]); tot-=max_flow(); printf("%d\n",tot); return 0; }
我爱学习,学习使我快乐