cogs 2221. [SDOI2016 Round1] 数字配对
★★ 输入文件:pair.in 输出文件:pair.out 简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
【输入格式】
第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。
【输出格式】
一行一个数,最多进行多少次配对。
【样例输入】
3
2 4 8
2 200 7
-1 -2 1
【样例输出】
4
【提示】
测试点 1 ~ 3:n≤10,ai≤109,bi=1,∣ci∣≤105;
测试点 4 ~ 5:n≤200,ai≤109,bi≤105,ci=0;
测试点 6 ~ 10:n≤200,ai≤109,bi≤105,∣ci∣≤105。
题解:
首先看到让你求匹配,想到网络流中的二分图匹配,然而一个数字只能进行一次匹配,想了很长时间都不知道如何限流,如果直接判断能否匹配是无法确定流量的,正确做法如下:
X1/X2结果是质数,说明讲两个数分解质因数之后,X1的质因子比X2的质因子多1,其余质因子一样。所以X1,X2的质因子的个数的奇偶性不同。由此可以看到,将N个数分解质因数之后,因子数相同的两个数一定不会匹配,所以把数字按照质因子个数分成两个集合,就形成了二分图中的X集和Y集。
二分答案,用最大费用最大流来判断,如果流量等于二分的数值且最大费用大于等于0,则成立。
还有,这题数据范围较坑,inf=1e9还不够。。。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;
const LL inf=1e15;
LL a[],b[],c[],d[],N,MAX;
LL prime[],tot;
bool p[][];
vector<LL> X,Y;
struct Edge{
LL to,rest,next,cost;
}e[];
LL head[],cnt=; inline void addedge(LL x,LL y,LL r,LL z){
e[++cnt].to=y; e[cnt].rest=r; e[cnt].cost= z; e[cnt].next=head[x]; head[x]=cnt;
e[++cnt].to=x; e[cnt].rest=; e[cnt].cost=-z; e[cnt].next=head[y]; head[y]=cnt;
} LL S,T,maxflow,mincost,dis[],pre[];
bool vis[]; inline bool SPFA(){
static queue<LL> Q;
while(!Q.empty()) Q.pop();
for(LL i=;i<=T;i++) dis[i]=-inf,vis[i]=false;
Q.push(S); dis[S]=; vis[S]=true;
while(!Q.empty()){
LL x=Q.front(); Q.pop(); vis[x]=false;
for(LL i=head[x];i;i=e[i].next){
LL y=e[i].to;
if(e[i].rest>&&(dis[y]<dis[x]+e[i].cost||dis[y]==-inf)){
dis[y]=dis[x]+e[i].cost;
pre[y]=i;
if(vis[y]==false){
vis[y]=true;
Q.push(y);
}
}
}
}
if(dis[T]>-inf) return true;
return false;
}
inline void update(){
LL flow=inf;
for(LL i=pre[T];i;i=pre[e[i^].to])
flow=min(flow,e[i].rest);
for(LL i=pre[T];i;i=pre[e[i^].to]){
e[i].rest-=flow;
e[i^].rest+=flow;
mincost+=flow*e[i].cost;
}
maxflow+=flow;
}
inline void ASK(){
maxflow=; mincost=;
while(SPFA())
update();
}
inline bool jud(LL x){
S=; T=N+;
for(LL i=;i<=cnt+;i++){
e[i].cost=e[i].next=e[i].rest=e[i].to=;
}
for(LL i=;i<=N+;i++) head[i]=,pre[i]=;
cnt=;
for(LL i=;i<X.size();i++){
addedge(S,X[i],b[X[i]],);
}
for(LL i=;i<X.size();i++){
for(LL j=;j<Y.size();j++){
if(p[X[i]][Y[j]]==true){
addedge(X[i],Y[j],inf,c[X[i]]*c[Y[j]]);
}
}
}
for(LL i=;i<Y.size();i++){
addedge(Y[i],N+,b[Y[i]],);
}
addedge(N+,T,x,);
ASK();
if(mincost>=&&maxflow==x) return true;
return false;
}
inline LL find(LL l,LL r){
if(l+>=r){
if(jud(r)==true) return r;
else return l;
}
LL mid=(l+r)>>;
if(jud(mid)==true) return find(mid,r);
else return find(l,mid-);
}
inline void shai(){
for(LL i=;i<=N;i++){
for(LL j=;j<=N;j++){
if((a[i]>a[j])&&(a[i]%a[j]==)){
LL tmp=a[i]/a[j]; bool hhh=true;
for(LL k=;k*k<=tmp&&k<=tmp;k++){
if(tmp%k==){
hhh=false; break;
}
}
if(hhh==true){
p[i][j]=p[j][i]=true;
// cout<<i<<" "<<j<<endl;
}
}
}
}
}
inline void calc(LL x){
LL tmp=a[x];
for(LL i=;i*i<=tmp&&i<=tmp;i++){
while(tmp%i==){
tmp/=i;
d[x]++;
}
}
if(tmp!=) d[x]++;
}
int main(){
scanf("%lld",&N);
for(LL i=;i<=N;i++) scanf("%lld",&a[i]);
for(LL i=;i<=N;i++) scanf("%lld",&b[i]),MAX+=b[i];
for(LL i=;i<=N;i++) scanf("%lld",&c[i]);
shai();
for(LL i=;i<=N;i++) calc(i);
for(LL i=;i<=N;i++){
if(d[i]%==) X.push_back(i);
else Y.push_back(i);
}
printf("%lld",find(,inf));
return ;
}
cogs 2221. [SDOI2016 Round1] 数字配对的更多相关文章
- Cogs 2221. [SDOI2016 Round1] 数字配对(二分图)
[SDOI2016 Round1] 数字配对 ★★★ 输入文件:menci_pair.in 输出文件:menci_pair.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述] 有 ...
- [SDOI2016 Round1] 数字配对
COGS 2221. [SDOI2016 Round1] 数字配对 http://www.cogs.pro/cogs/problem/problem.php?pid=2221 ★★★ 输入文件:m ...
- 「SDOI2016」数字配对
「SDOI2016」数字配对 题目大意 传送门 题解 \(a_i\) 是 \(a_j\) 的倍数,且 \(\frac{a_i}{a_j}\) 是一个质数,则将 \(a_i,a_j\) 质因数分解后,其 ...
- 【BZOJ4514】【SDOI2016】数字配对 [费用流]
数字配对 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ...
- [SDOI2016][bzoj4514] 数字配对 [费用流]
题面 传送门 思路 一个数字能且只能匹配一次 这引导我们思考:一次代表什么?代表用到一定上限(b数组)就不能再用,同时每用一次会产生价值(c数组) 上限?价值?网络流! 把一次匹配设为一点流量,那产生 ...
- cogs 2223. [SDOI2016 Round1] 生成魔咒
★★☆ 输入文件:menci_incantation.in 输出文件:menci_incantation.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述]魔咒串由许多魔咒字符组 ...
- 【LOJ】#2031. 「SDOI2016」数字配对
题解 这个图是个二分图,因为如果有一个奇环的话,我们会发现一个数变成另一个数要乘上个数不同的质数,显然不可能 然后我们发现这个不是求最大流,而是问一定价值的情况下最大流是多少,二分一个流量,加上一条边 ...
- loj2031 「SDOI2016」数字配对
跑最大费用最大流,注意到每次 spfa 出来的 cost 一定是越来越少的,啥时小于 \(0\) 了就停了吧. #include <iostream> #include <cstri ...
- 图论(费用流):BZOJ 4514 [Sdoi2016]数字配对
4514: [Sdoi2016]数字配对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 820 Solved: 345[Submit][Status ...
随机推荐
- 隐马尔可夫(HMM)
https://www.zhihu.com/question/20962240 作者:Yang Eninala链接:https://www.zhihu.com/question/20962240/an ...
- 正则表达式(三):Unicode诸问题下篇(转)
原文:http://www.infoq.com/cn/news/2011/04/regular-expressions-4 我们使用正则表达式,熟练掌握各种功能和结构只是手段,解决实际的问题才是真正的 ...
- 共享访问在.NET中的编程实现
转载:http://blog.csdn.net/zhzuo/article/details/1732937 共享访问在.NET中的编程实现 发布日期:2007-08-08 | 更新日期:2009-03 ...
- backreference Oracle正則表達式中的反向引用
这是Oracle对正則表達式的backreference的描写叙述 从定义中能够看到,当匹配表达式中已()的形式将一个子串包括起来.后面就能够以\? 的形式来引用.\1相应第一个(),\2相应第二 ...
- Java-idea-设置类头注释和方法注释
一.文件级别的注释 主要是通过File-->Setting-->Editor→File and Code Template中来设置 可以再右侧include中设置File ...
- windows环境下为php打开ssh2扩展
安装步骤 1. 下载 php extension ssh2下载地址 http://windows.php.net/downloads/pecl/releases/ssh2/0.12/ 根据自己PHP的 ...
- vue学习之node.js
Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装.本文详细介绍了No ...
- selenium webdriver窗口切换(下)
多窗口切换有时候需要在不同的窗口切换,从而操作不同的窗口上的元素.在selenium1.0 中这个问题比较难处理.但WebDriver 提供了switcTo.window()方法可以切换到任意的窗口. ...
- STA分析(三) cmos模型
CMOS集成电路的基本结构是以P型材料作为衬底(p-substrate),直接生成NMOS, 同时增加N肼(n-well),在其上制造PMOS. 增加两个bulk(P+,N+)防止非MOS管内的PN结 ...
- 将Pytorch模型从CPU转换成GPU
1. 如何进行迁移 对模型和相应的数据进行.cuda()处理.通过这种方式,我们就可以将内存中的数据复制到GPU的显存中去.从而可以通过GPU来进行运算了. 1.1 判定使用GPU 下载了对应的GPU ...