3308: 九月的咖啡店
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 140 Solved: 49
Description
深绘里在九份开了一家咖啡让,如何调配咖啡民了她每天的头等大事
我们假设她有N种原料,第i种原料编号为i,调配一杯咖啡则需要在这
里若干种兑在一起。不过有些原料不能同时在一杯中,如果两个编号
为i,j的原料,当且仅当i与j互质时,才能兑在同一杯中。
现在想知道,如果用这N种原料来调同一杯咖啡,使用的原料编号之和
最大可为多少。
Input
一个数字N
Output
如题
Sample Input
10
Sample Output
30
HINT
1<=N<=200000
直观感受是,所有质因数分别单独存在于一个数中
但是还要考虑到,俩个质因数一起存在于一个数中可以更优
如3,5,n=20
9+5<3*5
听说,至多俩个质因数存在于一个数中0.0
且一个大于根号n,一个小于根号n
于是就能费用流最大费用匹配了(不断增广至费用<0)
一个优化是,先假设所有质因数单独存在,把这部分收益加入答案
若a,b能配对
a,b连边 权值Vab−Va−VbVab−Va−Vb
这样费用流就跑的飞起了
WA了8次。。
附上本蒟蒻的代码:
#include
#include
#include
#include
using namespace std;
#define inf 1000000000
#define MAXN 200001
int ans,n,tot,T,cnt=1,dis[MAXN],h[MAXN],prime[MAXN],q[MAXN],head,tail;
bool mark[MAXN],vis[MAXN];
vector<int>q1,q2;
struct kx
{
int to,next,v,c;
}edge[MAXN*10];
int read()
{
int w=0,c=1; char ch=getchar();
while (ch<'0' || ch>'9')
{
if (ch=='-') c=-1;
ch=getchar();
}
while (ch>='0' && ch<='9')
w=w*10+ch-'0',ch=getchar();
return w*c;
}
void add(int u,int v,int w,int cost)
{
cnt++,edge[cnt]=(kx){v,h[u],w,cost};h[u]=cnt;
cnt++,edge[cnt]=(kx){u,h[v],0,-cost};h[v]=cnt;
}
bool spfa()
{
int i,now;
for (i=0;i<=T;i++) dis[i]=-inf;
head=0,tail=1,q[0]=T,dis[T]=0;
while (head!=tail)
{
now=q[head],head++;
if (head==200000) head=0;
vis[now]=0;
for (i=h[now];i;i=edge[i].next)
if (edge[i^1].v && dis[now]-edge[i].c>dis[edge[i].to])
{
dis[edge[i].to]=dis[now]-edge[i].c;
if (!vis[edge[i].to])
{
q[tail++]=edge[i].to;
if (tail==200000) tail=0;
vis[edge[i].to]=true;
}
}
}
return dis[0]>0;
}
int dfs(int x,int f)
{
mark[x]=true;
if (x==T) return f;
int w,used=0,i;
for (i=h[x];i;i=edge[i].next)
if (edge[i].v && dis[x]-edge[i].c==dis[edge[i].to] && !mark[edge[i].to])
{
w=dfs(edge[i].to,min(edge[i].v,f-used)),edge[i].v-=w,edge[i^1].v+=w;
ans+=edge[i].c*w,used+=w;
if (used==f) return f;
}
return used;
}
int v(int n,int x)
{
long long t=x;
while (x*t<=n) t*=x;
return t;
}
void build()
{
int i,a,b,tmp,j,t;
for (i=1;i<=tot;i++)
{
t=prime[i];
if (t*2>n)
{
ans+=t;
continue;
}
if ((long long)t*t<=n)
{
add(0,i,1,0);
ans+=v(n,t);
q1.push_back(i);
}
else
{
add(i,T,1,0);
ans+=t;
q2.push_back(i);
}
}
for (i=0;ifor (j=0;jif (a*b<=n)
{
tmp=v(n/b,a)*b;
if (tmp>v(n,a)+b)
add(q1[i],q2[j],1,tmp-(v(n,a)+b));
}
else break;
}
}
int main()
{
int i,j;
n=read();
for (i=2;i<=n;i++)
{
if (!mark[i]) prime[++tot]=i;
for (j=1;prime[j]*i<=n && j<=tot;j++)
{
mark[prime[j]*i]=true;
if (i%prime[j]==0) break;
}
}
T=n+1;
build();
while (spfa())
{
for (i=0;i<=T;i++) mark[i]=false;
mark[T]=true;
while (mark[T])
mark[T]=false,dfs(0,inf);
}
printf("%d",ans+1);
return 0;
}