数字配对

Time Limit: 10 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

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

Solution

  显然是一个费用流,并且这可以是一个二分图,由于 ai/aj 要是质数,那显然可以根据质因子个数的奇偶分类。

  然后跑一跑最大费用最大流。判断一下值要>=0即可统计入答案。mmpBearChild查了一个下午错,发现是INF开小了qaq。

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<map>
using namespace std;
typedef long long s64; const int ONE = *;
const int INF = ; int n;
int a[ONE], b[ONE], c[ONE];
s64 dist[ONE];
int vis[ONE], q[ONE*], pre[ONE];
int first[ONE], go[ONE], next[ONE], pas[ONE], from[ONE], tot;
int pNum[ONE];
int odd[ONE],Onum, eve[ONE],Enum;
int S, T, Ans;
int prime[ONE], isp[ONE], p;
s64 Val, w[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Getp(int MaxN)
{
for(int i=; i <= MaxN; i++)
{
if(!isp[i]) prime[++p] = i;
for(int j=; j <= prime[p], i*prime[j] <= MaxN; j++)
{
isp[i * prime[j]] = ;
if(i % prime[j] == ) break;
}
}
} int Factor(int x)
{
int res = ;
while(x != )
{
for(int i=; i<=p; i++)
if(x % prime[i] == )
{
x /= prime[i];
res++;
break;
}
}
return res;
} int PD(int x, int y)
{
if(x > y) swap(x, y);
if(x== || y== || y%x!=) return ;
x = y / x;
for(int i=; i<x; i++)
if(x % i == ) return ;
return ;
} int Add(int u, int v, int flow, s64 z)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v; pas[tot]=flow; w[tot]=z; from[tot]=u;
next[++tot]=first[v]; first[v]=tot; go[tot]=u; pas[tot]=; w[tot]=-z; from[tot]=v;
} bool Bfs()
{
for(int i=S; i<=T; i++) dist[i] = -1e18;
int tou = , wei = ;
q[] = S; vis[S] = ; dist[S] = ;
while(tou < wei)
{
int u = q[++tou];
for(int e=first[u]; e; e=next[e])
{
int v=go[e];
if(dist[v] < dist[u] + w[e] && pas[e])
{
dist[v] = dist[u] + w[e];
pre[v] = e;
if(!vis[v])
{
q[++wei] = v;
vis[v] = ;
}
}
}
vis[u] = ;
}
return dist[T] != -1e18;
} void Deal()
{
int x = INF;
for(int e=pre[T]; e; e=pre[from[e]]) x = min(x, pas[e]);
if(Val + dist[T] * x >= )
{
for(int e=pre[T]; e; e=pre[from[e]])
{
pas[e] -= x;
pas[((e-)^)+] += x;
}
Val += dist[T] * x;
Ans += x;
return;
}
printf("%d", Ans - Val / dist[T]);
exit();
} int main()
{
Getp(ONE);
n = get();
for(int i=; i<=n; i++) a[i] = get(), pNum[i] = Factor(a[i]);
for(int i=; i<=n; i++) b[i] = get();
for(int i=; i<=n; i++) c[i] = get(); S = ; T = n+;
for(int i=; i<=n; i++)
{
if(pNum[i] & ) Add(S,i, b[i],), odd[++Onum] = i;
else Add(i,T, b[i],), eve[++Enum] = i;
} for(int i=; i<=Onum; i++)
for(int j=; j<=Enum; j++)
{
int x = odd[i], y = eve[j];
if( PD(a[x], a[y]) )
Add(x,y, INF,(s64)c[x]*c[y]);
} while(Bfs()) Deal();
printf("%d", Ans - Val / dist[T]);
}

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

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

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

  2. 【BZOJ4514】[Sdoi2016]数字配对 费用流

    [BZOJ4514][Sdoi2016]数字配对 Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. mysql唯一查询

    MySQL单一字段唯一其他字段差异性忽略查询.在使用MySQL时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返 ...

  2. 从零讲JAVA ,给你一条 清晰地学习道路!该学什么就学什么!!

    1.计算机基础: 1.1数据机构基础: 主要学习:1.向量,链表,栈,队列和堆,词典.熟悉2.树,二叉搜索树.熟悉3.图,有向图,无向图,基本概念4.二叉搜索A,B,C类熟练,9大排序熟悉.5.树的前 ...

  3. 2018年小米高级 PHP 工程师面试题(模拟考试卷)

    1.通过哪一个函数,可以把错误转换为异常处理? A:set_error_handler B:error_reporting C:error2exception D:catch 正确答案:A 答案分析: ...

  4. TCP/IP三次握手与四次握手

    原文地址 http://blog.csdn.net/whuslei/article/details/6667471 http://blog.csdn.net/wo2niliye/article/det ...

  5. C#下载网页

    System.Net.WebClient wc = new System.Net.WebClient(); Byte[] pageData = wc.DownloadData("网页地址&q ...

  6. lalala

    <script type="text/javascript"> var a_idx = 0; var b_idx = 0; var a = new Array(&quo ...

  7. POJ1204:Word Puzzles——题解

    http://poj.org/problem?id=1204 题目大意:给一个字母表,求一些字符串的开端第一次出现的位置和字符串的方向(字符串可以按照八个方向放在字母表中可匹配的位置) ——————— ...

  8. oracle中varchar2字段存入blob字段及blob转成varchar2

    CREATE OR REPLACE FUNCTION C2B (b IN CLOB default empty_clob()) RETURN BLOB -- typecasts BLOB to CLO ...

  9. React Patterns

    Contents Stateless function JSX spread attributes Destructuring arguments Conditional rendering Chil ...

  10. Linux之socket套接字编程20160704

    介绍套接字之前,我们先看一下传输层的协议TCP与UDP: TCP协议与UDP协议的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UD ...