数字配对

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. C++读取文件统计单词个数及频率

    1.Github链接 GitHub链接地址https://github.com/Zzwenm/PersonProject-C2 2.PSP表格 PSP2.1 Personal Software Pro ...

  2. arcgis api for javascript 各个版本的SDK下载

    1.首先,进入下载网站,需要登录才能下载.下载链接 2.选择需要下载的版本,进行下载.

  3. PokeCats开发者日志(十三)

      现在是PokeCats游戏开发的第六十二天的晚上,把软著权登记证书的截图加上,又重新提交审核了一遍,但愿能过吧...

  4. placeholder 颜色

    /* placeholder颜色 */::-webkit-input-placeholder { /* WebKit browsers */color: #ccc;}:-moz-placeholder ...

  5. 【Python】Python time mktime()方法

    描述 Python time mktime() 函数执行与gmtime(), localtime()相反的操作,它接收struct_time对象作为参数,返回用秒数来表示时间的浮点数. 如果输入的值不 ...

  6. 【Python】python之set

    阅读目录 一.set集合介绍 二.集合的方法 1.s.add()添加元素 3.s.copy()浅拷贝 4.s.difference(b) 5.s.difference_update(b) 6.s.di ...

  7. 【bzoj4903/uoj300】[CTSC2017]吉夫特 数论+状压dp

    题目描述 给出一个长度为 $n$ 的序列,求所有长度大于等于2的子序列个数,满足:对于子序列中任意两个相邻的数 $a$ 和 $b$ ($a$ 在 $b$ 前面),${a\choose b}\mod 2 ...

  8. [BZOJ4589]Hard Nim

    description BZOJ 题意:\(n\)堆式子,每堆石子数量为\(\le m\)的质数,对于每一个局面玩\(Nim\)游戏,求后手必胜的方案数. data range \[n\le 10^9 ...

  9. BZOJ4898 & BZOJ5367 & 洛谷3778:[APIO2017]商旅——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4898 https://www.lydsy.com/JudgeOnline/problem.php? ...

  10. [Leetcode] permutations ii 全排列

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...