• [bzoj4514] [Sdoi2016]数字配对


     很好的题目.

     主要的思路是,按照质因子个数的奇偶性对这些数字分成左右两组.

     然后就在可以匹配的数字间连边,跑最长路费用流,一旦发现当前总价值要成为负值,结束费用流即可.

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iomanip>
    using namespace std;
    #define LL long long
    #define up(i,j,n) for(LL i=j;i<=n;i++)
    #define pii pair<LL,LL>
    #define db double
    #define eps 1e-10
    #define FILE "dealing"
    LL read(){
    	LL x=0,f=1,ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
    	return x*f;
    }
    const LL maxn=(LL)(1000000+3),inf=10000000000000000LL,limit=(LL)(6e5+0.1),mod=1000000007;
    bool cmin(LL& a,LL b){return a>b?a=b,true:false;}
    bool cmax(LL& a,LL b){return a<b?a=b,true:false;}
    LL n,a[3000],b[3000],c[3000],prime[maxn],top=0,S,T;
    namespace prepare{
    	LL b[maxn],n=(LL)(1e6+1);
    	void getprime(){
    		for(LL i=2;i<=n;i++){
    			if(!b[i])prime[++top]=i;
    			for(LL j=1;prime[j]*i<=n&&j<=top;j++){
    				b[i*prime[j]]=1;
    				if(i%prime[j]==0)break;
    			}
    		}
    	}
    };
    struct node{
    	LL y,next,rev,v,flow;
    }e[maxn];
    LL len,linkk[maxn];
    void insert(LL x,LL y,LL flow,LL v){
    //	printf("%d %d %d %d
    ",x,y,flow,v);
    	e[++len].y=y;
    	e[len].next=linkk[x];
    	linkk[x]=len;
    	e[len].rev=len+1;
    	e[len].flow=flow;
    	e[len].v=v;
    	
    	e[++len].y=x;
    	e[len].next=linkk[y];
    	linkk[y]=len;
    	e[len].rev=len-1;
    	e[len].flow=0;
    	e[len].v=-v;
    }
    LL q[maxn<<2],head=0,ans=0,maxflow=0,vis[3000],tail=0,flow[3000],d[3000],R[3000],pre[3000];
    bool SPFA(){
    	memset(vis,0,sizeof(vis));
    	up(i,S,T)d[i]=-inf;
    	tail=head=0;
    	q[++tail]=S;d[S]=0;
    	flow[S]=inf;vis[S]=1;
    	while(++head<=tail){
    		LL x=q[head];vis[x]=0;
    		for(LL i=linkk[x];i;i=e[i].next){
    			if(e[i].flow&&d[e[i].y]<d[x]+e[i].v){
    				d[e[i].y]=d[x]+e[i].v;
    				if(!vis[e[i].y])q[++tail]=e[i].y,vis[e[i].y]=1;
    				R[e[i].y]=i;
    				pre[e[i].y]=x;
    				flow[e[i].y]=min(flow[x],e[i].flow);
    			}
    		}
    	}
    	if(d[T]==-inf)return 0;
    	if(ans+d[T]*flow[T]<0){
    		maxflow+=(-ans)/(d[T]);
    		return 0;
    	}
    	else ans+=d[T]*flow[T],maxflow+=flow[T];
    	LL now=T;
    	while(now){
    		e[R[now]].flow-=flow[T];
    		e[e[R[now]].rev].flow+=flow[T];
    		now=pre[now];
    	}
    	return 1;
    }
    LL l[3000],r[3000],lcnt,rcnt;
    bool check(LL x){
    	if(x==1)return 0;
    	for(LL i=1;prime[i]*prime[i]<x;i++){
    		if(x%prime[i]==0)return 0;
    	}
    	return 1;
    }
    int main(){
    	//freopen(FILE".in","r",stdin);
    	//freopen(FILE".out","w",stdout);
    	n=read();
    	up(i,1,n)a[i]=read();
    	up(i,1,n)b[i]=read();
    	up(i,1,n)c[i]=read();
    	prepare::getprime();
    	up(i,1,n){
    		LL y=a[i],cnt=0;
    		up(j,1,top){
    			if(y==1)break;
    			while(y%prime[j]==0){
    				y/=prime[j];
    				cnt++;
    			}
    		}
    		if(y!=1)cnt++;
    		if(cnt%2)l[++lcnt]=i;
    		else r[++rcnt]=i;
    	}
    	S=0,T=n+1;
    	up(i,1,lcnt)insert(S,l[i],b[l[i]],0);
    	up(i,1,rcnt)insert(r[i],T,b[r[i]],0);
    	up(i,1,lcnt)up(j,1,rcnt){
    		if(a[l[i]]%a[r[j]]==0&&check(a[l[i]]/a[r[j]]))
    			insert(l[i],r[j],inf,c[l[i]]*c[r[j]]);
    		if(a[r[j]]%a[l[i]]==0&&check(a[r[j]]/a[l[i]]))
    			insert(l[i],r[j],inf,c[l[i]]*c[r[j]]);
    	}
    	while(SPFA());
    	printf("%lld
    ",maxflow);
    	return 0;
    }
    

      

  • 相关阅读:
    NB-IoT成为3GPP后会有哪些优势
    NB-IOT覆盖范围有多大 NB-IOT的强覆盖是怎么实现的
    4G DTU无线数据透明传输终端
    NB-IoT DTU是什么 NB-IoT的优势有哪些
    4G DTU是什么 4G DTU的功能和特点
    LoRa技术的发展应用和LoRa应用设备
    4G DTU为什么要具有透传的功能
    跨链在SIPC.VIP上的使用流程
    SimpleChain 开发挑战赛邀你来报名啦
    SimpleChain区块链管理系统使用教程
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6518891.html
Copyright © 2020-2023  润新知