【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

题解:一看到数据范围和大致题意,直接想到费用流,但是想了一会,发现建图好像并不容易。

为了方便分解质因数,我们现将1-100000中的质数都筛出来,这样我们可以较快速的判断两个数的商是否是质数。但是如何建图呢?这一些数好像很难构成一个二分图。但是如果我们将所有数按照所含的质因子总数奇偶分类,就得到了一个二分图,连边跑个最大费用流即可。

当我们找到一条增广路,使得增广后总权值为负时,直接特判一下最多还能流多少就行了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll inf=9223372036854775807;
int n,m,cnt,tot,S,T;
ll ans,sum;
int pri[100010],A[210],B[210],C[210],num[210],to[1000000],next[1000000],inq[210],pe[210],pv[210],head[210];
bool np[100010];
ll cost[1000000],flow[1000000],dis[210];
queue<int> q;
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
bool isp(int x)
{
if(x<=100000) return !np[x];
for(int i=1;i<=tot;i++) if(x%pri[i]==0) return 0;
return 1;
}
void add(int a,int b,ll c,ll d)
{
to[cnt]=b,cost[cnt]=c,flow[cnt]=d,next[cnt]=head[a],head[a]=cnt++;
to[cnt]=a,cost[cnt]=-c,flow[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
}
int bfs()
{
memset(dis,0x80,sizeof(dis));
int i,u;
q.push(S),dis[S]=0;
while(!q.empty())
{
u=q.front(),q.pop(),inq[u]=0;
for(i=head[u];i!=-1;i=next[i])
{
if(dis[to[i]]<dis[u]+cost[i]&&flow[i])
{
dis[to[i]]=dis[u]+cost[i],pe[to[i]]=i,pv[to[i]]=u;
if(!inq[to[i]]) inq[to[i]]=1,q.push(to[i]);
}
}
}
return dis[T]>(ll)0x8080808080808080;
}
int main()
{
n=rd(),S=0,T=n+1;
int i,j,tmp;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++) A[i]=rd();
for(i=1;i<=n;i++) B[i]=rd();
for(i=1;i<=n;i++) C[i]=rd();
for(np[1]=1,i=2;i<=100000;i++)
{
if(!np[i]) pri[++tot]=i;
for(j=1;j<=tot&&i*pri[j]<=100000;j++)
{
np[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
for(i=1;i<=n;i++)
{
tmp=A[i];
for(j=1;j<=tot&&pri[j]<=tmp;j++) while(tmp%pri[j]==0) tmp/=pri[j],num[i]++;
if(tmp!=1) num[i]++;
}
for(i=1;i<=n;i++)
{
if(num[i]&1)
{
add(S,i,0,B[i]);
for(j=1;j<=n;j++) if(abs(num[i]-num[j])==1)
if((A[i]%A[j]==0&&isp(A[i]/A[j]))||(A[j]%A[i]==0&&isp(A[j]/A[i]))) add(i,j,(ll)C[i]*C[j],inf);
}
else add(i,T,0,B[i]);
}
while(bfs())
{
ll mf=inf;
for(i=T;i!=S;i=pv[i]) mf=min(mf,flow[pe[i]]);
if(sum+mf*dis[T]<0)
{
ans+=sum/(-dis[T]);
break;
}
sum+=mf*dis[T],ans+=mf;
for(i=T;i!=S;i=pv[i]) flow[pe[i]]-=mf,flow[pe[i]^1]+=mf;
}
printf("%lld",ans);
return 0;
}

【BZOJ4514】[Sdoi2016]数字配对 费用流的更多相关文章

  1. bzoj4514: [Sdoi2016]数字配对--费用流

    看了一眼题目&数据范围,觉得应该是带下界的费用流 原来想拆点变成二分图,能配对的连边,跑二分图,可行性未知 后来看到另外一种解法.. 符合匹配要求的数要满足:质因子的个数相差为1,且两者可整除 ...

  2. BZOJ 4514: [Sdoi2016]数字配对 [费用流 数论]

    4514: [Sdoi2016]数字配对 题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数 ...

  3. BZOJ.4514.[SDOI2016]数字配对(费用流SPFA 二分图)

    BZOJ 洛谷 \(Solution\) 很显然的建二分图后跑最大费用流,但有个问题是一个数是只能用一次的,这样二分图两部分都有这个数. 那么就用两倍的.如果\(i\)可以向\(j'\)连边,\(j\ ...

  4. 【BZOJ 4514】[Sdoi2016]数字配对 费用流

    利用spfa流的性质,我直接拆两半,正解分奇偶(妙),而且判断是否整除且质数我用的是暴力根号,整洁判断质数个数差一(其他非spfa流怎么做?) #include <cstdio> #inc ...

  5. 4514: [Sdoi2016]数字配对 费用流

    链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4514 思路 EK直接贪心做 <0的时候加上剩余返回 二分图a->b的时候 把b- ...

  6. BZOJ4514[Sdoi2016]数字配对——最大费用最大流

    题目描述 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci ...

  7. 【BZOJ4514】【SDOI2016】数字配对 [费用流]

    数字配对 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ...

  8. bzoj4514: [Sdoi2016]数字配对(费用流)

    传送门 ps:费用流增广的时候费用和流量打反了……调了一个多小时 每个数只能参与一次配对,那么这就是一个匹配嘛 我们先把每个数分解质因数,记质因子总个数为$cnt_i$,那如果$a_i/a_j$是质数 ...

  9. [bzoj4514]数字配对[费用流]

    今年SDOI的题,看到他们在做,看到过了一百多个人,然后就被虐惨啦... 果然考试的时候还是打不了高端算法,调了...几天 默默地yy了一个费用流构图: 源连所有点,配对的点连啊,所有点连汇... 后 ...

随机推荐

  1. With语句在数据统计应用

    WITH TMP_EXECUTOR(EXECUTOR,EXECUTORNAME) AS ( SELECT DISTINCT T.EXECUTOR ,T1.FULLNAME AS EXECUTORNAM ...

  2. Educational Codeforces Round 34 A. Hungry Student Problem【枚举】

    A. Hungry Student Problem time limit per test 1 second memory limit per test 256 megabytes input sta ...

  3. Single Number II - LeetCode

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  4. 洛谷 P4256 公主の#19准备月考

    题目背景 公主在玩完游戏后,也要月考了.(就算是公主也要月考啊QWQ) 题目描述 公主的文综太差了,全校排名1100+(全校就1100多人),她分析了好久,发现她如果把所有时间放在选择题上,得分会比较 ...

  5. 2016北京集训测试赛(十七)Problem B: 银河战舰

    Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...

  6. 爬虫:网页里元素的xpath结构,scrapy不一定就找的到

    这种情况原因是html界面关联的js文件可能会动态修改DOM结构,这样浏览器完成了动态修改DOM,在 浏览器上看到的DOM结构,就和后台抓到的DOM结构不通 举例:新浪微博发的微博,在浏览器通过fir ...

  7. Python moni模拟鼠标事件

    7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 4 ...

  8. 17、Spring Boot普通类调用bean【从零开始学Spring Boot】

    转载:http://blog.csdn.net/linxingliang/article/details/52013017 我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个 ...

  9. STL之pair类型具体分析

    pair定义于头文件utility中.基本的作用是将两个数据组合成一个数据,两个数据能够是同一类型或者不同类型. pair类型提供的操作: pair<T1,T2> p1; pair< ...

  10. 常用组件介绍 ---- Layout_weight

      下面这些也可以算是组件 文本区 TextView 文本框 EditText layout  容器 view     千万不要把Layout_weight 与 Layout_width相混淆**** ...