3308: 九月的咖啡店

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit:
159  Solved: 56
[Submit][Status][Discuss]

Description

深绘里在九份开了一家咖啡让,如何调配咖啡民了她每天的头等大事我们假设她有N种原料,第i种原料编号为i,调配一杯咖啡则需要在这里若干种兑在一起。不过有些原料不能同时在一杯中,如果两个编号为i,j的原料,当且仅当i与j互质时,才能兑在同一杯中。现在想知道,如果用这N种原料来调同一杯咖啡,使用的原料编号之和最大可为多少。

Input

一个数字N

Output

如题

Sample Input

10

Sample Output

30

HINT

1<=N<=200000

Source

Solution

从N的范围,难以直接看出是网络流,但仔细分析,还是可以想到的

比较厉害的建图,首先需要两个结论

1.一个数的质因子,最多有两个

2.并且这两个质因子,一个小于$\sqrt{n}$,一个大于$\sqrt{n}$

那么可以考虑筛出1~n的素数

考虑建二分图

源向小于$\sqrt{n}$的质数连边,容量为1,费用为0

大于$\sqrt{n}$的质数向汇连边,容量为1,费用为0

小于$\sqrt{n}$的质数$a$向大于$\sqrt{n}$的质数$b$连边,容量为1,费用为$V_{ab}-V_{a}-V_{b}$

$V_{a}$表示单独选$a$的最大收益$V_{a}=a^{lgn/lga}$

$V_{b}$表示单独选$b$的最大收益$V_{b}=b$

$V_{ab}$表示同时选$a$和$b$的最大收益$V_{ab}=a^{lg(n/b)/lga}*b$

这样效率并不是特别的高,那么还可以加上两个优化:

1.如果一个质数>n/2,那么它只能单独选,不用连边

2.如果一条边的费用<0,那么完全可以不连

然后考虑 最大费用最大流 即可

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; char ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 200010
#define maxm 200000*10+10
#define inf 0x7fffffff
int n,ans;
struct Edgenode{int next,to,from,cap,cost;}edge[maxm];
int head[maxn],cnt=;
//init
inline void add(int u,int v,int w,int c)
{
cnt++; edge[cnt].next=head[u]; head[u]=cnt;
edge[cnt].from=u; edge[cnt].to=v; edge[cnt].cap=w; edge[cnt].cost=c;
}
inline void insert(int u,int v,int w,int c)
{add(u,v,w,c); add(v,u,,-c);}
//addedge
bool mark[maxn];int dis[maxn],S,T;
inline bool spfa()
{
queue<int>q; memset(mark,,sizeof(mark));
for (int i=S; i<=T; i++) dis[i]=-inf;
q.push(S); mark[S]=; dis[S]=;
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]<dis[now]+edge[i].cost)
{
dis[edge[i].to]=dis[now]+edge[i].cost;
if (!mark[edge[i].to])
mark[edge[i].to]=,q.push(edge[i].to);
}
mark[now]=;
}
return dis[T]>;
}
inline int dfs(int loc,int low)
{
mark[loc]=;
if (loc==T) return low;
int w,used=;
for (int i=head[loc]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[loc]+edge[i].cost && !mark[edge[i].to])
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w; used+=w;
ans+=w*edge[i].cost; if (used==low) return low;
}
return used;
}
inline void zkw()
{
int tmp=;
while (spfa())
{
mark[T]=;
while (mark[T])
memset(mark,,sizeof(mark)),tmp+=dfs(S,inf);
}
}
//MaxflowMaxcost
bool flag[maxn]; int prime[maxn],tot;
inline void prework(int maxx)
{
flag[]=;
for (int i=; i<=maxx; i++)
{
if (!flag[i]) prime[++tot]=i;
for (int j=; j<=tot && i*prime[j]<=maxx; j++)
{
flag[i*prime[j]]=;
if (!(i%prime[j])) break;
}
}
}
//get prime
inline int calc(int n,int x)
{
long long t=x;
while (t*x<=n) t=t*x;
return t;
}
//calc
inline void make()
{
S=,T=tot+; int pos=;
for (int i=; i<=tot; i++)
{
if (prime[i]>=n/) {ans+=prime[i];continue;}
if ((long long)prime[i]*prime[i]<=n)
insert(S,i,,),ans+=calc(n,prime[i]);
else
pos=(!pos)?i:pos,insert(i,T,,),ans+=prime[i];
}
for (int i=; i<pos; i++)
for (int j=pos; j<=tot; j++)
{
if ((long long)prime[i]*prime[j]>n) break;
int tmp=calc(n/prime[j],prime[i])*prime[j]-calc(n,prime[i])-prime[j];
if (tmp>) insert(i,j,,tmp);
}
}
//build
int main()
{
n=read();
prework(n);
make();
zkw();
printf("%d\n",ans+);
return ;
}

忽略桑心病狂的inline.. && 自己YY的最大费用最大流...好像还可以?

【BZOJ-3308】九月的咖啡店 最大费用最大流 + 线性筛素数的更多相关文章

  1. 【BZOJ 3308】 3308: 九月的咖啡店 (费用流|二分图最大权匹配)

    3308: 九月的咖啡店 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 244  Solved: 86 Description 深绘里在九份开了一家咖 ...

  2. bzoj 3308: 九月的咖啡店【最大费用最大流】

    费用流里spfa最后的判断要写成dis[t]>=0而不是dis[t]!=-inf否则会WAWAWA-- #include<iostream> #include<cstdio&g ...

  3. bzoj 3308 九月的咖啡店

    题目大意: 求若干个<=n的数 两两互质 使和最大 求这个最大的和 思路: 显然,得到两个结论 1 最终的所有数都只能分解为两个质因数 2 这两个质因数 一个<根号n 一个>根号n ...

  4. BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流

    传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, ...

  5. BZOJ 1061 志愿者招募(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布 ...

  6. bzoj 1070 [SCOI2007]修车(最小费用最大流)

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3515  Solved: 1411[Submit][Status] ...

  7. BZOJ 1221: [HNOI2001] 软件开发(最小费用最大流)

    不知道为什么这么慢.... 费用流,拆点.... --------------------------------------------------------------------------- ...

  8. bzoj 3171: [Tjoi2013]循环格 最小费用最大流

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3171 题解: 首先我们很容易发现一个结论: 出现完美循环当且仅当所有点的出入度均为1 所 ...

  9. bzoj 1070: [SCOI2007]修车【最小费用最大流】

    一开始从客人角度想的,怎么建都不对 从一个修车工所接待的所有顾客花费的总时间来看,设一共有x个人,那么第一个修的对总时间的贡献是x*w1,第二个是(x-1)*w2-以此类推.所以把第i个修车工拆成n组 ...

随机推荐

  1. 个人PHP开发环境的选择与搭建

    入职一个多月,重新调整了一下自己电脑的开发环境,现在写出来,算是作为自己的笔记. 如果你是该文章的读者,请忍受文章内的所有小章节都没有具体的步骤. 因为平时还要打游戏(划掉),所以电脑系统一直是Win ...

  2. iOS十六进制和字符串的相互转换

    转换代码,崩溃日志有些是十六进制 NSString *dictString = [dict JSONFragment];//组合成的 dictString==={"content" ...

  3. Java daemon thread 守护线程

    守护线程与普通线程写法上基本么啥区别,在启动线程前, 调用线程对象的方法setDaemon(true),则可以将其设置为守护线程. 守护线程使用的情况较少,但并非无用,举例来说,JVM的垃圾回收.内存 ...

  4. JQuery阻止事件冒泡---阻止后续代码执行

    (1)什么是事件起泡 首先你要明白一点,当一个事件发生的时候,该事件总是有一个事件源,即引发这个事件的对象,一个事件不能凭空产生,这就是事件的发生. 当事件发生后,这个事件就要开始传播.为什么要传播呢 ...

  5. jQuery的prop和attr方法之间区别

    JQuery.attr(): Get the value of an attribute for the first element in the set of matched elements. J ...

  6. 通过ssh tunnel连接内网ECS和RDS

    通过ssh tunnel连接内网ECS和RDS 这里讲了ssh tunnel的原理.很清晰. 此后又给外网访问内网增加了一种思路.感觉特别棒. 拓宽了思路:

  7. 数据字典生成工具之旅(8):SQL查询表的约束默认值等信息

    上一篇代码生成工具里面已经用到了读取表结构的SQL,这篇将更加详细的介绍SQL SERVER常用的几张系统表和视图! 阅读目录 系统表视图介绍 实际应用 本章总结 工具源代码下载 学习使用 回到顶部 ...

  8. Qt学习笔记网络(一)

    Qt5 移除了QHttp是因为功能重复 用QNetworkAccessManager完全能搞定 新建一个控制台应用程序 看一下QNetworkAccessManager的帮助文档 需要添加Qt + = ...

  9. Python2.4-原理之函数

    此节来自于<Python学习手册第四版>第四部分 一.函数基础 函数的作用在每个编程语言中都是大同小异的,,这个表是函数的相关语句和表达式. 1.编写函数,a.def是可执行代码,pyth ...

  10. AR播放器

    一.项目需求 AR播放器:将一系列带透明通道的图片以一定的帧率连续显示,叠加载摄像头采集的画面之上,并播放声音. 此为最初级的AR技术,因为画面是事先渲染好的,固定不变的,所以实际上并不能实现“互动” ...