深绘里在九份开了一家咖啡让,如何调配咖啡民了她每天的头等大事
我们假设她有N种原料,第i种原料编号为i,调配一杯咖啡则需要在这
里若干种兑在一起。不过有些原料不能同时在一杯中,如果两个编号
为i,j的原料,当且仅当i与j互质时,才能兑在同一杯中。
现在想知道,如果用这N种原料来调同一杯咖啡,使用的原料编号之和
最大可为多少。
深绘里在九份开了一家咖啡让,如何调配咖啡民了她每天的头等大事
我们假设她有N种原料,第i种原料编号为i,调配一杯咖啡则需要在这
里若干种兑在一起。不过有些原料不能同时在一杯中,如果两个编号
为i,j的原料,当且仅当i与j互质时,才能兑在同一杯中。
现在想知道,如果用这N种原料来调同一杯咖啡,使用的原料编号之和
最大可为多少。
一个数字N
如题
zkw网络流不会写,强行加了个SPFA,感觉更慢了
这题很难想到呀,一开始以为就是所有只含有一个质因子且尽可能大的数加在一起,
比如n=200000的时候,找到所有小于200000的质数并将它们一个一个不停地次方直到无限接近于n然后加在一起就好了①,但这样不一定最大,有可能可以包含两个质因子!而现实就是,能达到最优的配料编号一定最多只含有两个质因子,且一个小于sqrt(n),另一个大于sqrt(n)
既然这样还是好办
因为小于sqrt(n)的个数非常少,不超过100个,那么可以建张图:
所有小于sqrt(n)的质数与源点连接一条流量为1,费用为0的边
所有大于sqrt(n)的质数与汇点连接一条流量为1,费用为0的边
所有小于sqrt(n)的质数和大于sqrt(n)的质数连接一条流量为1,费用为Vab-Va-Vb的边
其中Va = a^(lgn/lga),Vb = b,Vab = a^(lg(n/b)/lga)*b
如果这个费用小于0则直接不连边就好,最后答案就是最大费用最大流+①情况的值
#include
#include
#include
using namespace std;
#define LL long long
typedef struct Res
{
int next;
int to, from;
int flow, cost;
}Road;
Road G[2000005];
int head[200010], vis[200010], dis[200010], pri[200010], flag[200010] = {1,1}, S, T, cnt, n, ans;
void Add(int u, int v, int flow, int cost)
{
cnt++;
G[cnt].next = head[u];
head[u] = cnt;
G[cnt].from = u;
G[cnt].to = v;
G[cnt].flow = flow;
G[cnt].cost = cost;
}
int SPFA()
{
int now, i, v;
queue q;
memset(vis, 0, sizeof(vis));
memset(dis, -62, sizeof(dis)); //如果是求最小费用,初始化应该为很大的正数,下同
q.push(S);
vis[S] = 1;
dis[S] = 0;
while(q.empty()==0)
{
now = q.front();
q.pop();
vis[now] = 0;
for(i=head[now];i!=0;i=G[i].next)
{
v = G[i].to;
if(G[i].flow && dis[v]dis[now]+G[i].cost
{
dis[v] = dis[now]+G[i].cost;
if(vis[v]==0)
{
vis[v] = 1,
q.push(v);
}
}
}
}
if(dis[T]>0) //如果是求最小费用,这里改成dis[T]=n/2)
{
ans += pri[i];
continue;
}
if((LL)pri[i]*pri[i]<=n)
{
Add(S, i, 1, 0);
Add(i, S, 0, 0);
ans += Jud(n, pri[i]);
pos = i;
}
else
{
Add(i, T, 1, 0);
Add(T, i, 0, 0);
ans += pri[i];
}
}
for(i=1;i<=pos;i++)
{
for(j=pos+1;j<=sum;j++)
{
if((LL)pri[i]*pri[j]>n)
break;
temp = Jud(n/pri[j], pri[i])*pri[j]-Jud(n, pri[i])-pri[j];
if(temp>0)
{
Add(i, j, 1, temp);
Add(j, i, 0, -temp);
}
}
}
while(SPFA())
{
memset(vis, 0, sizeof(vis));
while(Sech(S, -1000000000))
memset(vis, 0, sizeof(vis));
}
printf("%d\n", ans+1);
return 0;
}