BZOJ4514: [Sdoi2016]数字配对

Posted mt-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4514: [Sdoi2016]数字配对相关的知识,希望对你有一定的参考价值。

Description

有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
 

Input

第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。
 
 

Output

 一行一个数,最多进行多少次配对

 

Sample Input

3
2 4 8
2 200 7
-1 -2 1

Sample Output

4

HINT

 

 n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5

 
 
毒瘤题。。。。
但说句公道话,这题很有意思,细节+想法巨多,在这里感谢欧老师的倾力帮助
首先我们想一想怎么连边,200*200*根号10^9铁定会炸
那该怎么搞??
那么就需要用到一个很好的想法:枚举每个质因子(欧老师是我的红太阳没有他我就死。。。)
欧老师说:
首先如果A[i]%A[j]==0且A[i]/A[j]是个质数,那么可以直接得出结论A[i]的质因子个数比A[j]的多1
有一种方法:枚举1~根号A[i],遇到能除的就除尽,那么这样子得出来的肯定是质因子个数(显而易见)
如果剩下来的不是1,那么铁定是一个质数
为什么??
因为你已经除到根号A[i]了,所以不会存在两个或以上大于根号A[i]的质数,否则就>A[i]了
那么连边之后就很好办了,可是。。。我不会打有下界的网络流
那我只能二分
可是如果强行清空的话又要超时。。。
所以还得memcpy
所有都得开long long
(代码显得略丑)
 
代码如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
struct dicnic{
    int x,y,next,other;
    ll d,c;
}a[41000],e[41000];
int len,tlen,last[41000],first[41000];

const ll INF=1ll<<61;
void inc(int x,int y,ll c,ll d)
{
    int k1,k2;
    k1=++tlen;
    e[tlen].x=e[tlen].x=x;e[tlen].y=y;e[tlen].c=c;e[tlen].d=d;
    e[tlen].next=first[x];first[x]=tlen;
    
    k2=++tlen;
    e[tlen].x=y;e[tlen].y=x;e[tlen].c=0;e[tlen].d=-d;
    e[tlen].next=first[y];first[y]=tlen;
    
    e[k1].other=k2;
    e[k2].other=k1;
}
void ins(int x,int y,ll c,ll d)
{
    int k1,k2;
    k1=++len;
    a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d;
    a[len].next=last[x];last[x]=len;
    
    k2=++len;
    a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d;
    a[len].next=last[y];last[y]=len;
    
    a[k1].other=k2;
    a[k2].other=k1;
}
int st,ed;
int pre[840],v[840];
ll d[840],cc[840];
int list[6*840],head,tail;
ll ans,sum;
bool spfa()
{
    for(int i=1;i<=ed+1;i++)d[i]=-INF;
    d[st]=0;
    memset(v,false,sizeof(v));v[st]=true;
    memset(cc,0,sizeof(cc));cc[st]=INF;
    list[1]=st;head=1;tail=2;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(a[k].c>0&&d[y]<d[x]+a[k].d)
            {
                d[y]=d[x]+a[k].d;
                pre[y]=k;
                cc[y]=min(cc[x],a[k].c);
                if(!v[y])
                {
                    v[y]=true;
                    list[tail++]=y;
                    if(tail==ed+1)tail=1;
                }
            }
        }
        head++;if(head==ed+1)head=1;
        v[x]=false;
    }
    if(d[ed]==-INF)return false;
    ans+=d[ed]*cc[ed];sum+=cc[ed];
    int x=ed;
    while(x!=0)
    {
        int k=pre[x];
        a[k].c-=cc[ed];a[a[k].other].c+=cc[ed];
        x=a[k].x;
    }
    return true;
}
int n;
ll A[210];
int f[210];
ll b[210],c[210];
bool check(ll x)
{
    len=tlen;
    memcpy(last,first,sizeof(last));
    memcpy(a,e,sizeof(a));ins(st,ed+1,x*2,0);
    ans=sum=0;
    while(spfa()==true)
    {    }
    if(sum==x*2&&ans>=0)return true;
    return false;
}
int main()
{
    ll xx=0;tlen=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&A[i]);int t=int(sqrt(double(A[i]+1)));ll x=A[i];
        for(int j=2;j<=t;j++) {
            while(x%j==0) {x/=j;f[i]++;}
        }if(x!=1)f[i]++;
    }
    for(int i=1;i<=n;i++)scanf("%lld",&b[i]),xx+=b[i];
    for(int i=1;i<=n;i++)scanf("%lld",&c[i]);
    ed=n*2+1;st=ed+1;
    for(int i=1;i<=n;i++)
    {
        inc(st,i,b[i],0);inc(i+n,ed,b[i],0);
        for(int j=1;j<=n;j++)
            if(A[i]%A[j]==0&&f[i]-f[j]==1)
                inc(i,j+n,INF,c[i]*c[j]),inc(j,i+n,INF,c[i]*c[j]);

    }
    st=ed+2;
    ll anss=0;
    ll l=0,r=xx*10;
    while(l<=r)
    {
        ll mid=(l+r)/2;
        if(check(mid)==true){l=mid+1,anss=mid;}
        else r=mid-1;
    }
    printf("%lld\n",anss);
    return 0;
}

by_lmy

以上是关于BZOJ4514: [Sdoi2016]数字配对的主要内容,如果未能解决你的问题,请参考以下文章

[Bzoj4514][Sdoi2016]数字配对(费用流)

图论(费用流):BZOJ 4514 [Sdoi2016]数字配对

BZOJ4514: [Sdoi2016]数字配对

BZOJ4514SDOI2016数字配对 [费用流]

bzoj4514: [Sdoi2016]数字配对 图论-费用流

bzoj4514 [Sdoi2016]数字配对(网络流)