「SDOI2016」数字配对

题目大意

传送门

题解

\(a_i\) 是 \(a_j\) 的倍数,且 \(\frac{a_i}{a_j}\) 是一个质数,则将 \(a_i,a_j\) 质因数分解后,其质因子的次数和相差为 \(1\)。

由此我们可以想到根据质因子次数和的奇偶性对 \(a_i\) 进行分组,不难发现会被分成两组。这让我们联想到了二分图。

我们考虑采用费用流求解。

首先我们可以将源点 \(s\) 向其中一组点连容量为 \(b_i\),费用为 \(0\) 的边,然后从另外一组点的每个点向汇点 \(t\) 连容量为 \(b_i\),费用为 \(0\) 的边,限制每个数能够被配对的次数。

然后我们可以在满足条件的点对 \((a_i,a_j)\) 间连一条容量为 \(\min(b_i,b_j)\),费用为 \(c_i\cdot c_j\) 的边。

最后跑最大费用最大流即可。

这里题目要求费用非负,所以在统计答案的时候处理一下使其在非负的条件下流最大即可。

注意有的地方需要开 \(\text{long long}\)。

/*---Author:HenryHuang---*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e2+5;
typedef long long ll;
struct edge{
int to,nex;
ll w,v;
}e[maxn*maxn*4];
int head[maxn],cur[maxn],tot=1;
void add(int a,int b,ll c,ll d){
e[++tot]=(edge){b,head[a],c,d};
head[a]=cur[a]=tot;
}
void add_edge(int a,int b,ll c,ll d){
add(a,b,c,d);
add(b,a,0,-d);
}
int solve(int n){
int i=2,ans=0;
while(i*i<=n){
while(n%i==0) ++ans,n/=i;
++i;
}
if(n!=1) ++ans;
return ans;
}
int a[maxn],b[maxn],c[maxn];
int cnt[maxn];
int n,m,s,t;
ll dis[maxn];
bool vis[maxn];
bool spfa(){
for(int i=0;i<=n+1;++i) cur[i]=head[i],dis[i]=-1ll<<60;
memset(vis,0,sizeof vis);
queue<int> Q;
dis[s]=0,vis[s]=1,Q.push(s);
while(!Q.empty()){
int u=Q.front();Q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(e[i].w&&dis[v]<dis[u]+e[i].v){
dis[v]=dis[u]+e[i].v;
if(!vis[v]) vis[v]=1,Q.push(v);
}
}
}
return dis[t]>-1ll<<60;
}
int dfs(int u,ll in){
if(u==t) return in;
ll out=0,tmp;
vis[u]=1;
for(int i=cur[u];i;i=e[i].nex){
int v=e[i].to;cur[u]=i;
if((!vis[v])&&e[i].w&&dis[v]==dis[u]+e[i].v&&(tmp=dfs(v,min(in,e[i].w)))){
e[i].w-=tmp,e[i^1].w+=tmp;
in-=tmp,out+=tmp;
}
}
if(!out) dis[u]=0;
vis[u]=0;
return out;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i) cin>>b[i];
for(int i=1;i<=n;++i) cin>>c[i];
s=0,t=n+1;
for(int i=1;i<=n;++i){
cnt[i]=solve(a[i]);
}
for(int i=1;i<=n;++i){
if(cnt[i]&1) add_edge(s,i,b[i],0);
else add_edge(i,t,b[i],0);
for(int j=1;j<=n;++j){
if(cnt[i]&1)
if((a[i]%a[j]==0&&cnt[j]+1==cnt[i])||(a[j]%a[i]==0&&cnt[i]+1==cnt[j]))
add_edge(i,j,1<<30,1ll*c[i]*c[j]);
}
}
ll ans=0,now=0,d=0;
int flag=0;
while(spfa()){
memset(vis,0,sizeof vis);
while(d=dfs(s,1ll<<60),d!=0){
memset(vis,0,sizeof vis);
if(now+d*dis[t]<0){
ans+=now/(-dis[t]);
flag=1;break;
}
ans+=d;
now+=d*dis[t];
}
if(flag) break;
}
cout<<ans<<'\n';
return 0;
}

「SDOI2016」数字配对的更多相关文章

  1. 【LOJ】#2031. 「SDOI2016」数字配对

    题解 这个图是个二分图,因为如果有一个奇环的话,我们会发现一个数变成另一个数要乘上个数不同的质数,显然不可能 然后我们发现这个不是求最大流,而是问一定价值的情况下最大流是多少,二分一个流量,加上一条边 ...

  2. loj2031 「SDOI2016」数字配对

    跑最大费用最大流,注意到每次 spfa 出来的 cost 一定是越来越少的,啥时小于 \(0\) 了就停了吧. #include <iostream> #include <cstri ...

  3. liberOJ #2033. 「SDOI2016」生成魔咒 后缀数组

    #2033. 「SDOI2016」生成魔咒     题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 11.2 22 拼凑起来形成一个魔咒串 [1,2] [1, 2] ...

  4. 「SDOI2016」储能表(数位dp)

    「SDOI2016」储能表(数位dp) 神仙数位 \(dp\) 系列 可能我做题做得少 \(QAQ\) \(f[i][0/1][0/1][0/1]\) 表示第 \(i\) 位 \(n\) 是否到达上界 ...

  5. loj#2128. 「HAOI2015」数字串拆分 矩阵乘法

    目录 题目链接 题解 代码 题目链接 loj#2128. 「HAOI2015」数字串拆分 题解 \(f(s)\)对于\(f(i) = \sum_{j = i - m}^{i - 1}f(j)\) 这个 ...

  6. [SDOI2016 Round1] 数字配对

    COGS 2221. [SDOI2016 Round1] 数字配对 http://www.cogs.pro/cogs/problem/problem.php?pid=2221 ★★★   输入文件:m ...

  7. [LOJ 2070] 「SDOI2016」平凡的骰子

    [LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...

  8. Cogs 2221. [SDOI2016 Round1] 数字配对(二分图)

    [SDOI2016 Round1] 数字配对 ★★★ 输入文件:menci_pair.in 输出文件:menci_pair.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述] 有 ...

  9. 「SDOI2016」征途 题解

    「SDOI2016」征途 先浅浅复制一个方差 显然dp,可以搞一个 \(dp[i][j]\)为前i段路程j天到达的最小方差 开始暴力转移 \(dp[i][j]=min(dp[k][j-1]+?)(j- ...

随机推荐

  1. CRC校验原理简介及C代码实现说明

    1 原理 参考文档:CRC校验 (qq.com) 参考书籍:<计算机网络(第7版)-谢希仁> 1.1 原理简介 CRC是一种检错方法. 在发送端,先把数据划分为组,假定每组k个比特.现假定 ...

  2. Nextcloud 使用教程

    一.简介 Nextcloud是一个网盘式文件管理系统,多用户权限管理,多客户端,使用简单.可在浏览器中运行,也可下客户端,不论使用哪种方式运行,使用教程都是一样的. 只是在客户端中运行时能及时收到相应 ...

  3. gin使用validator库参数校验若干实用技巧

    validator库参数校验若干实用技巧 本文介绍了使用validator库做参数校验的一些十分实用的使用技巧,包括翻译校验错误提示信息.自定义提示信息的字段名称.自定义校验方法等. validato ...

  4. Step By Step(Lua数据持久化)

    Step By Step(Lua数据持久化) 1. 数据文件:    我们可以利用Lua中table的构造式来定义一种文件格式,即文件中的数据是table构造并初始化的代码,这种方式对于Lua程序而言 ...

  5. 3D-LaneNet:端到端三维多车道检测ICCV2019

    3D-LaneNet:端到端三维多车道检测ICCV2019 3D-LaneNet: End-to-End 3D Multiple Lane Detection 论文链接: http://openacc ...

  6. javaBean命名规范 get / set 后的首字母大写

    javaBean命名规范 Sun 推荐的命名规范 1 ,类名要首字母大写,后面的单词首字母大写 2 ,方法名的第一个单词小写,后面的单词首字母大写 3 ,变量名的第一个单词小写,后面的单词首字母大写 ...

  7. SpringCloud01:微服务概述

    一.什么是微服务 微服务是一种架构风格,是一种架构设计方式,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独立部署,各个微服务之间是松耦合的.每个微服务仅关注于完成一件任务并很好地 ...

  8. 端午总结Vue3中computed和watch的使用

    1使用计算属性 computed 实现按钮是否禁用 我们在有些业务场景的时候,需要将按钮禁用. 这个时候,我们需要使用(disabled)属性来实现. disabled的值是true表示禁用.fals ...

  9. 使用allure工具生成测试报告(基于pytest框架)

    一.allure简介:一个轻量级的,灵活的,支持多语言,多平台的开源report框架 Allure基于标准的xUnit结果输出,但是添加了一些补充数据.任何报告都是通过两个步骤生成的.在测试执行期间( ...

  10. 『居善地』接口测试 — 12、Moco框架介绍

    目录 1.Mock功能介绍 2.Moco框架介绍 3.Moco框架在接口测试中的作用 4.Moco框架的优点 5.Moco框架的下载与启动 (1)Moco框架的下载 (2)Moco框架的启动 1.Mo ...