题意

现在你有一个集合{1,2,3,...,n},要求你从中取出一些元素,使得这些元素两两互质。问你能够取出的元素总和最多是多少?

输入格式

一个整数n

输出格式

一个整数表示能够选出的最大的元素总和。

思路

这道题居然是结论+网络流?根本想不到啊...~~

感觉写题解都只能照搬官方题解了~~

首先出题人就给了两个自己也没有证出来的结论:

  1. 最后选出的数至多只有两个不同的质因子
  2. 每个选出的数val所包含的质因子如果有两个的话,一定是一个小于\(\sqrt{val}\),还有一个是大于\(\sqrt{val}\)。

至于为什么呢?好像没有人知道...

然后我们考虑建图。如果暴力建图(就是像二分图那样),将所有的质因子分为两个部,左边是小于等于\(\sqrt {n}\)的,右边是大于\(\sqrt {n}\),然后两个部之间两两连边就可以了。但是这样子边的数量好像多了一点..."据说"可能会T(没试过)。

那么就是优化。

首先,先定义F(pri[1],pri[2]...pri[k])为包含pri[]这些质因子的最大的小于等于n的数。然后我们能够发现,F(pri[1]),F(pri[2]),F(pri[3])...F(pri[pri.size()-1])这些数字是比较优秀的。

然后由于分成了两个部,我们考虑左边一个数质数x,右边一个数质数y,如果我们加入F(x,y)的话,我们能够发现F(x)和F(y)就不能选了。那么就会获得\(F(x,y)-F(x)-F(y)\)的贡献。只有当这个值大于0的时候,我们才将这条边加进去。

宏观感受下,这样子之后边的数量就变得很少了...然后你可以过了...

建图的话,就是源点S连向左边的部,容量为1,费用为0;

左边的部按照上述方式向右边的部连边,容量为1,费用为\(F(x,y)-F(x)-F(y)\);

右边的部向汇点T连边,容量为1,费用为0。

然后跑一个最大费用流(注意不是最大流!!wa了好久!!注意当当前求出来的费用小于0时需要退出!!否则答案就会偏小),在加上最开始的初始值(\(\sum_{i=1}^{k}F(pri[i])\)),就是最后的答案了。

代码

我的实现是建立负权边跑最小费用流,可能具体细节和上述的做法是反着的。如果你采用SPFA求最长路的话,细节和上面就是一样的了。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<vector>
  5. #include<queue>
  6. #define MAXN 200000
  7. #define INF 1000000000000000000LL
  8. using namespace std;
  9. typedef long long LL;
  10. struct node
  11. {
  12. int to;
  13. LL cap,cost;
  14. node *nxt,*bck;
  15. }edges[MAXN*10+5];
  16. node *ncnt=&edges[0],*Adj[MAXN+5];
  17. int S,T,n;
  18. vector<LL> prime,p1,p2;
  19. bool vis[MAXN+5],inque[MAXN+5];
  20. LL maxval[MAXN+5],dist[MAXN+5],d[MAXN+5];
  21. int prevv[MAXN+5];
  22. node *preve[MAXN+5];
  23. queue<int> que;
  24. void Sieve()
  25. {
  26. for(int i=2;i<=n;i++)
  27. {
  28. if(vis[i]==false)
  29. prime.push_back(i);
  30. for(int j=0;1LL*prime[j]*i<=n;j++)
  31. {
  32. vis[i*prime[j]]=true;
  33. if(i%prime[j]==0)
  34. break;
  35. }
  36. }
  37. }
  38. LL F(LL x,LL y)
  39. {
  40. LL ret=y;//由于y>sqrt(n),所以y这个质因子在ret中只会出现一次
  41. while(1LL*ret*x<=n)
  42. ret*=x;
  43. return ret;
  44. }
  45. void AddEdge(int u,int v,LL cap,LL cost)
  46. {
  47. node *p=++ncnt;
  48. p->to=v;p->cap=cap;p->cost=cost;
  49. p->nxt=Adj[u];Adj[u]=p;
  50. node *q=++ncnt;
  51. q->to=u;q->cap=0;q->cost=-cost;
  52. q->nxt=Adj[v];Adj[v]=q;
  53. p->bck=q;q->bck=p;
  54. }
  55. void Build()
  56. {
  57. S=0,T=(int)prime.size()+1;
  58. for(int i=0;i<(int)prime.size();i++)
  59. if(1LL*prime[i]*prime[i]<=n)
  60. AddEdge(S,i+1,1,0),p1.push_back(i);
  61. else
  62. AddEdge(i+1,T,1,0),p2.push_back(i);
  63. for(int i=0;i<(int)p1.size();i++)
  64. for(int j=0;j<(int)p2.size();j++)
  65. {
  66. LL num1=prime[p1[i]],num2=prime[p2[j]];
  67. LL num=F(num1,num2);
  68. if(num-maxval[p1[i]]-maxval[p2[j]]>0)
  69. {
  70. // printf("val:%lld\n",num-maxval[p1[i]]-maxval[p2[j]]);
  71. AddEdge(p1[i]+1,p2[j]+1,1,-num+maxval[p1[i]]+maxval[p2[j]]);
  72. }
  73. }
  74. }
  75. void SPFA()
  76. {
  77. while(que.empty()==false)
  78. que.pop();
  79. memset(inque,0,sizeof(inque));
  80. fill(dist,dist+T+1,INF);
  81. fill(d,d+T+1,INF);
  82. dist[S]=0;
  83. que.push(S);inque[S]=true;
  84. while(que.empty()==false)
  85. {
  86. int u=que.front();
  87. que.pop();inque[u]=false;
  88. for(node *p=Adj[u];p!=NULL;p=p->nxt)
  89. {
  90. int v=p->to;
  91. LL w=p->cost;
  92. if(p->cap&&dist[v]>dist[u]+w)
  93. {
  94. if(inque[v]==false)
  95. inque[v]=true,que.push(v);
  96. d[v]=min(d[u],p->cap);
  97. dist[v]=dist[u]+w;
  98. prevv[v]=u;preve[v]=p;
  99. }
  100. }
  101. }
  102. }
  103. LL Min_Cost_Flow()
  104. {
  105. LL flow=0,cost=0,delta;
  106. int u,v;
  107. while(true)
  108. {
  109. SPFA();
  110. if(d[T]==INF||dist[T]>=0)//就是这里,一定要判一下!!!否则答案偏小
  111. break;
  112. delta=d[T];
  113. for(v=T;v!=S;v=u)
  114. {
  115. u=prevv[v];
  116. node *&p=preve[v];
  117. p->cap-=delta;
  118. p->bck->cap+=delta;
  119. cost+=1LL*p->cost*delta;
  120. }
  121. }
  122. return cost;
  123. }
  124. int main()
  125. {
  126. scanf("%d",&n);
  127. Sieve();
  128. LL ans=1LL;
  129. for(int i=0;i<(int)prime.size();i++)
  130. maxval[i]=F(prime[i],1LL),ans+=maxval[i];//先确定初始的值
  131. // printf("%lld\n",ans);
  132. Build();
  133. ans-=min(0LL,Min_Cost_Flow());//加上可能存在的更有的方案(应该可以不用取min,懒得改了...)
  134. printf("%lld\n",ans);
  135. return 0;
  136. }

【2019雅礼集训】【最大费用流】【模型转换】D2T3 sum的更多相关文章

  1. 【2019雅礼集训】【可持久化线段树】【模型转化】D1T2Permutation

    目录 题意 输入格式 输出格式 思路 代码 题意 给定一个长度为n的序列A[],你需要确定一个长度为n的排列P[],定义当前排列的值为: \[\sum_{i=1}^{n}{A[i]P[i]}\] 现在 ...

  2. 【2019雅礼集训】【CF 960G】【第一类斯特林数】【NTT&多项式】permutation

    目录 题意 输入格式 输出格式 思路 代码 题意 找有多少个长度为n的排列,使得从左往右数,有a个元素比之前的所有数字都大,从右往左数,有b个元素比之后的所有数字都大. n<=2*10^5,a, ...

  3. 雅礼集训2019 D7T2 Subsequence

    雅礼集训2019 D7T2 Subsequence 直接贴题解: 平衡树代码: #include<bits/stdc++.h> #define ll long long #define N ...

  4. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  5. 雅礼集训【Day6-1】字符串

    雅礼集训[Day6-1]字符串 假设我们有串\(a\),我们设\(a'\)为\(a\)翻转后按为取反过后的串. 我们只考虑前一半的,长为\(m\)的串.如果前半截匹配了\(a\)或者\(a'\),则\ ...

  6. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

  7. 「雅礼集训 2017 Day2」解题报告

    「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...

  8. 「雅礼集训 2017 Day1」 解题报告

    「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...

  9. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

随机推荐

  1. ArcGis Python脚本——将细碎小面合并到相邻的面积最大的面

    参数: polygon_fc 面要素类 area_limit 给定面积值,小于它的面会被合并 给定两个参数即可,这回没有注释. #polygon_fc 面要素类 #area_limit 给定面积值,小 ...

  2. ElasticSearch Index操作源码分析

    ElasticSearch Index操作源码分析 本文记录ElasticSearch创建索引执行源码流程.从执行流程角度看一下创建索引会涉及到哪些服务(比如AllocationService.Mas ...

  3. 13、Ajax的使用

    一.AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. a).AJAX = 异步 JavaScript 和 XML. b).AJAX 是一种用于创建快速动态网页的技术. 通过在后 ...

  4. springMVC中数据流解析与装载

    最近在看springmvc原理时,看到一篇比较赞的博文,留存学习,如果侵权,请告知,立删. 地址: https://my.oschina.net/lichhao/blog/172562

  5. Linux CentOS7 安装wkhtmltopdf工具

    wkhtmltopdf是一款将html文件转换成pdf格式的优秀的文件内容转换工具.它使用QT作为渲染引擎,目前它的RELEASE版尚不支持flex布局的Html5代码转换.使用flex的嵌套元素将会 ...

  6. Standford NLP study

    Homepage https://stanfordnlp.github.io/CoreNLP/index.html Source Code: https://github.com/stanfordnl ...

  7. Request method 'POST' not supported解决办法

    (1)考虑拦截器是否将该链接拦截

  8. E: Unable to locate package clang-7 E: Unable to locate package clang++-7 E: Couldn't find any package by regex 'clang++-7'

    我的系统是Debian 9.8, 然后在装下面这两个包的时候老是提示找不到.然后再github上一问,过了几分钟就有大佬回复了,而且亲测有效 ~$ sudo apt-get -y install cl ...

  9. numpy数组取每一列的数据

    也可以运用到列表中,a原本是一个列表的嵌套,将a转为了数组进行此操作,可以取固定的值,这就是numpy的好处.

  10. WPF 10天修炼 第八天 - 形状、画刷和变换

    图形 在WPF中使用绘图最简单的就是使用Shape类.Shape类继承自FrameworkElement,是一个专门用来绘图的类.Shape类中年派生的类有直线.矩形.多边形和圆形等. System. ...