NOIP2017提高组 模拟赛13(总结)

第一题 函数

【题目描述】



【输入格式】

  三个整数。

  1≤t<109+7,2≤l≤r≤5*106

【输出格式】

  一个整数。

【输出样例】

2 2 4

【输出样例】

19

【解题思路】

  证明:对于n个人,分解成质因数,按质数个人分为一组(从小到大)。

  例如:30可以分成2 * 3 * 5,那么一开始2人为一组,共有15组。再分成3人为一组,然后有5组。再分成5人一组,有1组。

  为什么这是最优的?



  a,b是n的质因数

  设\(\frac{n}{ab}=x\)

  \(bx\frac{a(a-1)}{2}+x\frac{b(b-1)}{2}=\frac{bx}{2}(a²-a+b-1)\)



  \(x\frac{ab(ab-1)}{2}=\frac{bx}{2}(a²b-a)\)

  ∵a,b>=2

  ∴(a²b-a)>(a²-a+b-1)

  由(a²-a+b-1)可得,a<b会比a>b优。

  证毕。

【代码】

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. typedef long long ll;
  5. const ll mods=1e9+7;
  6. const int N=7000000;
  7. int pr[N],lp,n,L,R,t;
  8. bool inp[N],re[N];
  9. ll F[N],ans,tl;
  10. void getpr()
  11. {
  12. inp[1]=1;
  13. for(int i=2;i<=n;i++)
  14. {
  15. if(!inp[i]) { pr[++lp]=i; F[i]=(((ll)i*(i-1))>>1)%mods; re[i]=1; }
  16. for(int j=1;(ll)i*pr[j]<=n && j<=lp;j++)
  17. {
  18. F[pr[j]*i]=(F[pr[j]]*i%mods+F[i])%mods;
  19. inp[pr[j]*i]=1;
  20. if(!(i%pr[j])) break;
  21. }
  22. }
  23. }
  24. int main()
  25. {
  26. freopen("2233.in","r",stdin);
  27. freopen("2233.out","w",stdout);
  28. scanf("%d%d%d",&t,&L,&R);
  29. n=R; getpr(); tl=1ll; ans=0ll;
  30. for(int i=L;i<=R;i++)
  31. {
  32. ll k=F[i];
  33. ans=(ans+tl*k%mods)%mods;
  34. tl=tl*t%mods;
  35. }
  36. printf("%lld\n",ans);
  37. return 0;
  38. }

第二题 部落

【题目描述】

  部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全毁坏。

  现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间。

同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。

  如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。

你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。

【输入格式】

  第一行一个整数N

  接下来N行每行两个整数T1,T2,表示修该建筑需要T1秒,要在T2秒之前修完。

【输出格式】

  一个整数表示最多能抢救的建筑数量。

【输入样例】

4

100 200

200 1300

1000 1250

2000 3200

【输出样例】

3

【数据规模】

  对于40%的数据,T2<=1000000

  对于100%的数据,N <= 150,000; T1 < T2 < maxlongint

【解题思路】

  一个简单的推论:假若建筑i的T2<建筑j的T2,而且建筑i的T1≥建筑j的T1,总时间+T1<建筑j的T2,那么将i替换成j,答案会更优。(贪心)

  所以,用大根堆维护最大值,每次将最大值判断一下,是否需要替换掉即可。

【代码】

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. typedef long long ll;
  5. const ll mods=1e9+7;
  6. const int N=150500;
  7. struct data { int a,b,id; } d[N];
  8. int n,ans,h[N],cnt;
  9. bool cmp(data A,data B) { return (A.b<B.b); }
  10. void add(int x)
  11. {
  12. cnt++; h[cnt]=x;
  13. int now=cnt;
  14. while((now>1) && (d[h[now>>1]].a<d[h[now]].a))
  15. {
  16. swap(h[now>>1],h[now]);
  17. now>>=1;
  18. }
  19. }
  20. void down()
  21. {
  22. h[1]=h[cnt]; cnt--;
  23. int now=1;
  24. while((now<<1)<=cnt)
  25. {
  26. int uw;
  27. if((now<<1|1)>cnt) uw=now<<1; else uw=(d[h[now<<1]].a>d[h[now<<1|1]].a)?(now<<1):(now<<1|1);
  28. if(d[h[now]].a<d[h[uw]].a) swap(h[now],h[uw]); else break;
  29. now=uw;
  30. }
  31. }
  32. int main()
  33. {
  34. freopen("2234.in","r",stdin);
  35. freopen("2234.out","w",stdout);
  36. scanf("%d",&n);
  37. for(int i=1;i<=n;i++) scanf("%d%d",&d[i].a,&d[i].b),d[i].id=i;
  38. sort(d+1,d+1+n,cmp);
  39. int tim=0;
  40. for(int i=1;i<=n;i++)
  41. {
  42. if(tim+d[i].a<=d[i].b)
  43. {
  44. tim+=d[i].a;
  45. ans++; add(i);
  46. } else
  47. {
  48. int yu=h[1];
  49. if(d[yu].a>d[i].a)
  50. {
  51. tim+=d[i].a-d[yu].a;
  52. down(); add(i);
  53. }
  54. }
  55. }
  56. printf("%d\n",ans);
  57. return 0;
  58. }

第三题 sunny图(原题 codeforces 603E)

【题目描述】



【输入格式】

  第一行两个整数n和m。

  接下来m行每行三个整数。ai,bi,li。

【输出格式】

  共m行,每行一个整数表示每次操作的答案。

【输入样例】

4 4

1 3 4

2 4 8

1 2 2

3 4 3

【输出样例】

-1

8

8

3

【数据规模】

  1≤ai,bi≤n,1≤li≤10^9

  对于20%的数据,2≤n小于等于15,1≤m≤15。

  对于40%的数据,2≤n小于等于100,1≤m≤100。

  对于60%的数据,2≤n小于等于500,1≤m≤2000。

  对于100%的数据,2≤n小于等于100000,1≤m≤300000。

【解题思路】

  一个重要的推论(然而并没有推出来):

  将图分成若干个联通块,每个联通块的点数均为偶数,那么就是sunny图。

  为什么?(分类讨论)

  假如有一个偶数点的图,一定可以划分成一棵树。

  那么设根节点为father,father的点数为奇数的儿子sonY一定为奇数个,奇 * 奇+偶 * (偶 或 奇)+1=偶。那么将sonX与father的边cut掉,就满足了father的度数为奇数(奇数条与儿子的边)的情况。

  那么点数为奇数的儿子sonY,仍保留与father的边。那么sonY的点数为奇数的儿子Y一定有偶数个,奇 * 偶+偶 * (偶 或 奇)+1=奇。那么将X与sonY的边cut掉,就满足了sonY的度数为奇数(偶数条与儿子的边+与父亲的边)的情况。

  点数为偶数的儿子sonX的情况与第一种类似(是完全一样好吧)。

  那么,树是自己造的,边随便搞,加入一条x->y的边,若x,y之前已经连通,就把路径上的最大边删了,加入新边(在新边小于最大边的情况下)

  至于联通块分成两个偶数块,判断删除最大边L后,剩下的两个联通块点数是否为偶数就行了。

  需要用LCT维护子树大小。

  具体应该是这样:

  多个splay树通过parent边相连。

  在每个splay树记录一个sub,表示整棵splay树的奇偶(仅仅是splay树)

  再记一个all,表示整个子树i包括相连的splay树的奇偶(在splay树合并或断开的时候更新)

【代码】

  1. //codeforce 603E
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<set>
  5. #define imax(a,b) ((a>b)?(a):(b))
  6. #define imin(a,b) ((a<b)?(a):(b))
  7. using namespace std;
  8. const int N=400010;
  9. struct tree { int mx,val,sub,all,zi; } s[N];
  10. int c[N][2],fa[N],rev[N];
  11. int H[N],ht,W[N];
  12. int n,m,odd,cnt;
  13. int stack[N];
  14. //int F[N];
  15. struct godD { int a,b,l; } d[N];
  16. //set <pair<int,int> > hp;
  17. bool gd(int x) { return (c[fa[x]][1]==x); }
  18. bool isroot(int x) { return (c[fa[x]][0]!=x && c[fa[x]][1]!=x); }
  19. int MAX(int x,int y)
  20. {
  21. if(!x || !y) return x+y;
  22. return ((s[x].val>s[y].val)?(x):(y));
  23. }
  24. void up(int x)
  25. {
  26. s[x].all=s[x].sub^s[x].zi;
  27. s[x].mx=x;
  28. if(c[x][0]) s[x].all^=s[c[x][0]].all;
  29. if(c[x][1]) s[x].all^=s[c[x][1]].all;
  30. s[x].mx=MAX(s[x].mx,s[c[x][0]].mx);
  31. s[x].mx=MAX(s[x].mx,s[c[x][1]].mx);
  32. }
  33. void down(int x)
  34. {
  35. if(rev[x])
  36. {
  37. rev[x]^=1;
  38. rev[c[x][0]]^=1; rev[c[x][1]]^=1;
  39. swap(c[x][0],c[x][1]);
  40. }
  41. }
  42. void rotate(int x)
  43. {
  44. int y=fa[x],z=fa[y];
  45. int l=gd(x),r=!l;
  46. if(!isroot(y)) c[z][gd(y)]=x;
  47. fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
  48. c[y][l]=c[x][r]; c[x][r]=y;
  49. up(y); up(x);
  50. }
  51. void splay(int x)
  52. {
  53. int hy=0; stack[++hy]=x;
  54. for(int i=x;!isroot(i);i=fa[i]) stack[++hy]=fa[i];
  55. for(int i=hy;i;i--) down(stack[i]);
  56. for(;!isroot(x);)
  57. {
  58. int y=fa[x];
  59. if(!isroot(y)) (gd(x)^gd(y))?rotate(x):rotate(y);
  60. rotate(x);
  61. }
  62. }
  63. void access(int x)
  64. {
  65. int y=0;
  66. while(x)
  67. {
  68. splay(x);
  69. down(x);
  70. if(y) s[x].sub^=s[y].all;
  71. if(c[x][1]) s[x].sub^=s[c[x][1]].all;
  72. c[x][1]=y;
  73. up(x);
  74. y=x;
  75. x=fa[x];
  76. }
  77. }
  78. void evert(int x)
  79. {
  80. access(x); splay(x); rev[x]^=1;
  81. }
  82. int findroot(int x)
  83. {
  84. access(x); splay(x);
  85. while(c[x][0]) x=c[x][0];
  86. return x;
  87. }
  88. void link(int x,int y)
  89. {
  90. evert(x); evert(y);
  91. fa[x]=y; s[y].sub^=s[x].all;
  92. up(y);
  93. }
  94. void cut(int x,int y)
  95. {
  96. evert(x); access(y); splay(y);
  97. fa[x]=0; c[y][0]=0;
  98. up(y);
  99. }
  100. void Cut(int u)
  101. {
  102. int x=d[u].a,y=d[u].b;
  103. cut(x,u+n); cut(y,u+n);
  104. }
  105. bool cle(int u)
  106. {
  107. int x=d[u].a,y=d[u].b;
  108. cut(x,u+n); cut(y,u+n);
  109. if(!s[x].all && !s[y].all) return 1;
  110. link(x,u+n); link(y,u+n);
  111. return 0;
  112. }
  113. void add(int x)
  114. {
  115. H[++ht]=x; int now=ht;
  116. while((now>1) && d[H[now>>1]].l<d[H[now]].l)
  117. {
  118. swap(H[now>>1],H[now]);
  119. now>>=1;
  120. }
  121. }
  122. void hdown()
  123. {
  124. H[1]=H[ht--]; int now=1;
  125. while((now<<1)<=ht)
  126. {
  127. int uw;
  128. if(((now<<1)|1)>ht) uw=(now<<1); else uw=(d[H[now<<1]].l>d[H[now<<1|1]].l)?(now<<1):(now<<1|1);
  129. if(d[H[now]].l<d[H[uw]].l)
  130. {
  131. swap(H[now],H[uw]);
  132. } else break;
  133. now=uw;
  134. }
  135. }
  136. //int findroot(int x) { return ((F[x]<0)?(x):(F[x]=findroot(F[x]))); }
  137. /*void uni(int x,int y)
  138. {
  139. int ix=findroot(x),iy=findroot(y);
  140. if(F[ix]>F[iy]) swap(ix,iy);
  141. F[ix]+=F[iy]; F[iy]=ix;
  142. }*/
  143. int main()
  144. {
  145. freopen("2235.in","r",stdin);
  146. freopen("2235.out","w",stdout);
  147. scanf("%d%d",&n,&m);
  148. odd=n; ht=0;
  149. for(int i=1;i<=n;i++) s[i].all=s[i].zi=1;
  150. for(int i=1;i<=m;i++)
  151. {
  152. int lx,ly,cost;
  153. scanf("%d%d%d",&lx,&ly,&cost);
  154. d[i].a=lx; d[i].b=ly; d[i].l=cost;
  155. s[i+n].val=cost; s[i+n].mx=i+n;
  156. if(findroot(lx)!=findroot(ly))
  157. {
  158. evert(lx); evert(ly);
  159. if(s[lx].all && s[ly].all) odd-=2;
  160. link(lx,i+n); link(ly,i+n);
  161. W[i]=1; add(i); //uni(lx,ly);
  162. //hp.insert(make_pair(-cost,i));
  163. } else
  164. {
  165. evert(ly); access(lx); splay(lx);
  166. int yu=s[lx].mx;
  167. if(s[yu].val>cost)
  168. {
  169. Cut(yu-n);
  170. link(lx,i+n); link(ly,i+n);
  171. W[i]=1; W[yu-n]=0; add(i);
  172. //hp.erase(make_pair(-s[yu].val,yu-n));
  173. //hp.insert(make_pair(-cost,i));
  174. }
  175. }
  176. if(odd==0)
  177. {
  178. for(;;)
  179. {
  180. int yu=H[1];
  181. if(!W[yu] || cle(yu)) hdown(); else break;
  182. }
  183. printf("%d\n",d[H[1]].l);
  184. } else printf("-1\n");
  185. /*if(odd==0)
  186. {
  187. for(;;)
  188. {
  189. int e=(*hp.begin()).second;
  190. if(cle(e)) hp.erase(hp.begin()); else break;
  191. }
  192. printf("%d\n",-(*hp.begin()).first);
  193. } else printf("-1\n");*/
  194. }
  195. return 0;
  196. }

NOIP2017提高组 模拟赛13(总结)的更多相关文章

  1. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  2. NOIP2017提高组模拟赛 10 (总结)

    NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...

  3. NOIP2017提高组模拟赛 8(总结)

    NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...

  4. NOIP2017提高组模拟赛 9 (总结)

    NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...

  5. NOIP2017提高组模拟赛 7(总结)

    NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...

  6. NOIP2017提高组模拟赛5 (总结)

    NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...

  7. NOIP2017提高组模拟赛4 (总结)

    NOIP2017提高组模拟赛4 (总结) 第一题 约数 设K是一个正整数,设X是K的约数,且X不等于1也不等于K. 加了X后,K的值就变大了,你可以重复上面的步骤.例如K= 4,我们可以用上面的规则产 ...

  8. 计蒜客NOIP2017提高组模拟赛(三)day1

    火山喷发 火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 n 个生物分别具有 A​1​​,A​2​​,⋯,A​n​​点生命值,一次火山喷发总计 MM 轮 ...

  9. 计蒜客NOIP2017提高组模拟赛(四)day1

    T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...

随机推荐

  1. VS2013找不到SDKDDKVer.h

    今天在升级vs2010 的project的时候遇到了一个这种问题.提示:找不到SDKDKVer.h 通过查找资料发现,原来是vs版本号之间Windows SDK的路径宏定义不同,有些坑. 网上有人说能 ...

  2. angularjs1-2,作用域、代码压缩

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. xargs用例一个

    ls -a *.doc|awk -F. '{print $1}' |xargs -I {} java -jar ~/soft/jodconverter-2.2.2/lib/jodconverter-c ...

  4. zzulioj--1769--去师院的旅程:能怎么走(三)(0.0)

    1796: 去师院的旅程:能怎么走(三) Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 404  Solved: 200 SubmitStatusWe ...

  5. 深度理解Jquery 中 scrollTop() 方法

    这是工作遇到scrollTop() 方法.为了强化自己,把它记录在博客园当中. 下面就开始scrollTop 用法讲解: scrollTop() 定义和用法 scrollTop() 方法设置或返回被选 ...

  6. checkbox改写

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. MVC、控件、一般处理程序中的session and cookie

    Mvc中: session: if (!string .IsNullOrEmpty(find)) //设置 Session["oip"] = "无锡"; Vie ...

  8. EntityFramework使用及优化

    1. 简介 ORM框架:Object Relation Mapping,用操作对象的方式来操作数据库 其它框架:Dapper.NHibernate,首推EF,微软官方的. EF底层还是ADO.NET实 ...

  9. 查看md文件

    使用命令将md文件转为html,在浏览器中演示 通过npm安装i5ting_toc 安装好node之后,可以直接使用npm.Windows+R打开运行框,输入cmd,打开命令窗口.连网的情况下,输入如 ...

  10. Spring meven 配置

    使用maven的仓库化管理,可以更方便有效的控制文件. 在官网下载maven. 官网的地址:http://maven.apache.org/download.cgi  请选择最新的版本下载, 这里我用 ...