zoukankan      html  css  js  c++  java
  • bzoj3275: Number

    最小割。。。然后推一下可知不能的情况必定为一奇一偶,于是s->奇->偶->t。跑最小割即可。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #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 REP(i,s,t) for(int i=s;i<=t;i++)
    #define op() clr(head,0);pt=edges;
    #define qwq(x) for(edge *o=head[x];o;o=o->next)
    int read(){
    	int x=0;char c=getchar();bool f=true;
    	while(!isdigit(c)) {
    		if(c=='-') f=false;c=getchar();
    	}
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    	return x;
    }
    const int nmax=3005;
    const int maxn=6000005;
    const int inf=0x7f7f7f7f;
    struct edge{
    	int to,cap;edge *next,*rev;
    };
    edge edges[maxn],*pt,*head[nmax],*p[nmax],*cur[nmax];
    int cnt[nmax],h[nmax],g[nmax];
    void add(int u,int v,int w){
    	pt->to=v;pt->cap=w;pt->next=head[u];head[u]=pt++;
    }
    void adde(int u,int v,int w){
    	add(u,v,w);add(v,u,0);head[u]->rev=head[v];head[v]->rev=head[u];
    }
    int maxflow(int s,int t,int n){
    	clr(cnt,0);cnt[0]=n;clr(h,0);
    	int flow=0,a=inf,x=s;edge *e;
    	while(h[s]<n){
    		for(e=cur[x];e;e=e->next) if(e->cap>0&&h[x]==h[e->to]+1) break;
    		if(e){
    			a=min(a,e->cap);p[e->to]=cur[x]=e;x=e->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[h[x]]) break;
    			h[x]=n;
    			for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) 
    			  h[x]=h[e->to]+1,cur[x]=e;
    			cnt[h[x]]++;
    			if(x!=s) x=p[x]->rev->to;
    		}
    	}
    	return flow;
    }
    int gcd(int x,int y){
    	return y==0?x:gcd(y,x%y);
    }
    bool check(int x,int y){
    	if(gcd(x,y)!=1) return false;
    	int tmp=x*x+y*y,temp=sqrt(tmp);
    	if(temp*temp==tmp) return true;
    	return false;
    }
    int main(){
    	op();
    	int n=read(),s=0,t=n+1,ans=0;
    	rep(i,n){
    		g[i]=read();ans+=g[i];
    		g[i]%2?adde(s,i,g[i]):adde(i,t,g[i]);
    	}
    	rep(i,n) if(g[i]%2) rep(j,n) if(!(g[j]%2)) 
    	   if(check(g[i],g[j])) adde(i,j,inf);
    	/*REP(i,s,t) {
    		qwq(i) printf("%d ",o->to);printf("
    ");
    	}*/
    	printf("%d
    ",ans-maxflow(s,t,t+1));
    	return 0;
    }
    

      

    3275: Number

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 778  Solved: 329
    [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个正整数a1,a2,?an。
     
     

    Output

    最大的和。
     

    Sample Input

    5
    3 4 5 6 7



    Sample Output

    22


    HINT

    n<=3000。

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    Qt之json解析
    ListView
    JAVA的文件操作【转】
    可以随着SeekBar滑块滑动显示的Demo
    Android 之Buletooth
    VC++之运算符重载简单小结
    Android之Audio和Video
    Android之内容提供者ContentProvider的总结
    Android之Intent
    Android之Activity小结
  • 原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5666197.html
Copyright © 2011-2022 走看看