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. SQL80001: Incorrect syntax near ':'

    原文连接:http://geekswithblogs.net/tonyt/archive/2010/03/05/138363.aspx   SQL80001: Incorrect syntax nea ...

  2. HTTP下密码的安全传输、OAuth认证

    在复杂的web环境下,我们没有百分的把握保证信息在传输的过程中不被接货,那不是用明文如何告诉服务器自己的身份呢? 在一些高度通信安全的网络中,数据传输会使用HTTPS作为传输协议,但是通常情况下我们没 ...

  3. Java 8 Lambda表达式探险

    为什么?    我们为什么需要Lambda表达式    主要有三个原因:    > 更加紧凑的代码      比如Java中现有的匿名内部类以及监听器(listeners)和事件处理器(hand ...

  4. Http概述(一)

    Http使用的是可靠的数据传输协议,因此即使数据来自地球的另一端,也能够确保数据在传输过程中不会被损坏或产生混乱. 这样用户在访问信息时就不用担心其完整性了. web服务端与服务器是如何通信的 Web ...

  5. EF分页中的陷阱

    (一) 前言                                                                   EF使用非常简单,但是如果使用不当就会误入EF陷阱中. ...

  6. Log4net使用(三)

    第一步 public class logger { private static ILog Info; private static ILog Error; private static ILog W ...

  7. [BZOJ3714][PA2014]Kuglarz(MST)

    题目: Description 魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品.花费c_ij元,魔术师就会告诉你杯子 ...

  8. SEO站点优化学习总结

    1.网站收录查询 在搜索引擎里面输入Site:域名 即可. 尾巴——学习SEO可以看看以下几个网站: 卢松松博客[一个草根的博客]:http://lusongsong.com/ 站长之家[里面有站长统 ...

  9. 东大OJ-1391-Big big Power

    题目描述 Calculate the power num a^(b^c) mod 1e9+7 输入 Multiple test cases,each case has three integers a ...

  10. kill 根据PID终止进程

    根据PID终止进程 kill [option] PID-list kill 通过向一个或多个进程发送信号来终止进程.除超级用户外,只有进程的所有者才可以对进程执行kill 参数 PID-list为ki ...