NOIP2015 D1 解题报告
T1 神奇的幻方
题目描述
幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行、每列及两条对角线上的数字之和都相同。
当N为奇数时,我们可以通过以下方法构建一个幻方:
首先将1写在第一行的中间。
之后,按如下方式从小到大依次填写每个数K(K=2,3,…,N*N):
1.若(K−1)在第一行但不在最后一列,则将K填在最后一行,(K−1)所在列的右一列;
2.若(K−1)在最后一列但不在第一行,则将K填在第一列,(K−1)所在行的上一行;
3.若(K−1)在第一行最后一列,则将K填在(K−1)的正下方;
4.若(K−1)既不在第一行,也不在最后一列,如果(K−1)的右上方还未填数,则将K填在(K−1)的右上方,否则将K填在(K−1)的正下方。
现给定N请按上述方法构造N*N的幻方。
输入输出格式
输入格式:
输入文件只有一行,包含一个整数N即幻方的大小。
输出格式:
输出文件包含N行,每行N个整数,即按上述方法构造出的N*N的幻方。相邻两个整数之间用单个空格隔开。
输入输出样例
- 3
- 8 1 6
- 3 5 7
- 4 9 2
- 25
- 327 354 381 408 435 462 489 516 543 570 597 624 1 28 55 82 109 136 163 190 217 244 271 298 325
- 353 380 407 434 461 488 515 542 569 596 623 25 27 54 81 108 135 162 189 216 243 270 297 324 326
- 379 406 433 460 487 514 541 568 595 622 24 26 53 80 107 134 161 188 215 242 269 296 323 350 352
- 405 432 459 486 513 540 567 594 621 23 50 52 79 106 133 160 187 214 241 268 295 322 349 351 378
- 431 458 485 512 539 566 593 620 22 49 51 78 105 132 159 186 213 240 267 294 321 348 375 377 404
- 457 484 511 538 565 592 619 21 48 75 77 104 131 158 185 212 239 266 293 320 347 374 376 403 430
- 483 510 537 564 591 618 20 47 74 76 103 130 157 184 211 238 265 292 319 346 373 400 402 429 456
- 509 536 563 590 617 19 46 73 100 102 129 156 183 210 237 264 291 318 345 372 399 401 428 455 482
- 535 562 589 616 18 45 72 99 101 128 155 182 209 236 263 290 317 344 371 398 425 427 454 481 508
- 561 588 615 17 44 71 98 125 127 154 181 208 235 262 289 316 343 370 397 424 426 453 480 507 534
- 587 614 16 43 70 97 124 126 153 180 207 234 261 288 315 342 369 396 423 450 452 479 506 533 560
- 613 15 42 69 96 123 150 152 179 206 233 260 287 314 341 368 395 422 449 451 478 505 532 559 586
- 14 41 68 95 122 149 151 178 205 232 259 286 313 340 367 394 421 448 475 477 504 531 558 585 612
- 40 67 94 121 148 175 177 204 231 258 285 312 339 366 393 420 447 474 476 503 530 557 584 611 13
- 66 93 120 147 174 176 203 230 257 284 311 338 365 392 419 446 473 500 502 529 556 583 610 12 39
- 92 119 146 173 200 202 229 256 283 310 337 364 391 418 445 472 499 501 528 555 582 609 11 38 65
- 118 145 172 199 201 228 255 282 309 336 363 390 417 444 471 498 525 527 554 581 608 10 37 64 91
- 144 171 198 225 227 254 281 308 335 362 389 416 443 470 497 524 526 553 580 607 9 36 63 90 117
- 170 197 224 226 253 280 307 334 361 388 415 442 469 496 523 550 552 579 606 8 35 62 89 116 143
- 196 223 250 252 279 306 333 360 387 414 441 468 495 522 549 551 578 605 7 34 61 88 115 142 169
- 222 249 251 278 305 332 359 386 413 440 467 494 521 548 575 577 604 6 33 60 87 114 141 168 195
- 248 275 277 304 331 358 385 412 439 466 493 520 547 574 576 603 5 32 59 86 113 140 167 194 221
- 274 276 303 330 357 384 411 438 465 492 519 546 573 600 602 4 31 58 85 112 139 166 193 220 247
- 300 302 329 356 383 410 437 464 491 518 545 572 599 601 3 30 57 84 111 138 165 192 219 246 273
- 301 328 355 382 409 436 463 490 517 544 571 598 625 2 29 56 83 110 137 164 191 218 245 272 299
说明
对于100%的数据,1<=N<=39且N为奇数。
- /*模拟就好了*/
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- int n;
- int map[][];
- struct num
- {
- int x,y;
- }a[];
- int main()
- {
- //freopen("magic.in","r",stdin);
- //freopen("magic.out","w",stdout);
- scanf("%d",&n);
- a[].x=,a[].y=(n>>)+(n&);
- map[a[].x][a[].y]=;
- for(int i=;i<=n*n;i++)
- {
- if(a[i-].x==&&a[i-].y!=n)
- {
- a[i].x=n;
- a[i].y=a[i-].y+;
- }
- else if(a[i-].x!=&&a[i-].y==n)
- {
- a[i].x=a[i-].x-;
- a[i].y=;
- }
- else if(a[i-].x==&&a[i-].y==n)
- {
- a[i].x=;
- a[i].y=n;
- }
- else if(a[i-].x!=&&a[i-].y!=n)
- {
- if(!map[a[i-].x-][a[i-].y+])
- {
- a[i].x=a[i-].x-;
- a[i].y=a[i-].y+;
- }
- else
- {
- a[i].x=a[i-].x+;
- a[i].y=a[i-].y;
- }
- }
- map[a[i].x][a[i].y]=i;
- }
- for(int i=;i<=n;i++)
- {
- for(int j=;j<=n;j++)
- {
- printf("%d ",map[i][j]);
- }
- printf("\n");
- }
- //fclose(stdin);fclose(stdout);
- return ;
- }
T2 信息传递
题目描述
有n个同学(编号为1到n)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学。
游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自己的生日时,游戏结束。请问该游戏一共可以进行几轮?
输入输出格式
输入格式:
输入共2行。
第1行包含1个正整数n表示n个人。
第2行包含n个用空格隔开的正整数T1,T2,……,Tn其中第i个整数Ti示编号为i
的同学的信息传递对象是编号为Ti的同学,Ti≤n且Ti≠i
数据保证游戏一定会结束。
输出格式:
输出共 1 行,包含 1 个整数,表示游戏一共可以进行多少轮。
输入输出样例
- 5
- 2 4 2 3 1
- 3
说明
样例1解释
游戏的流程如图所示。当进行完第 3 轮游戏后, 4 号玩家会听到 2 号玩家告诉他自
己的生日,所以答案为 3。当然,第 3 轮游戏后, 2 号玩家、 3 号玩家都能从自己的消息
来源得知自己的生日,同样符合游戏结束的条件。
对于 30%的数据, n ≤ 200;
对于 60%的数据, n ≤ 2500;
对于 100%的数据, n ≤ 200000。
- /*
- 跑tarjan找缩点,所有缩点中点的数量的大于1的最小值就是答案。
- 因为每个缩点都是一个强连通分量,所以其中的点一定可以相互到达,那么所包含的最小的点数就是传的最少的次数。
- */
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- #define N 200005
- using namespace std;
- int n,top,tim,num,sum,ans;
- int to[N],dfn[N],low[N],point[N];
- int stack[N];
- bool visited[N];
- void tarjan(int u)
- {
- dfn[u]=low[u]=++tim;
- stack[++top]=u;
- visited[u]=;
- if(!dfn[to[u]])
- {
- tarjan(to[u]);
- low[u]=min(low[u],low[to[u]]);
- }
- else if(visited[to[u]])
- low[u]=min(low[u],dfn[to[u]]);
- if(dfn[u]==low[u])
- {
- ++sum;
- do
- {
- num=stack[top--];
- point[sum]++;
- visited[num]=;
- }while(u!=num);
- }
- return;
- }
- int main()
- {
- //freopen("message.in","r",stdin);
- //freopen("message.out","w",stdout);
- scanf("%d",&n);
- for(int i=;i<=n;i++)
- {
- scanf("%d",&to[i]);
- }
- for(int i=;i<=n;i++)
- {
- if(!dfn[i])
- tarjan(i);
- }
- ans=<<;
- for(int i=;i<=sum;i++)
- {
- if(point[i]<ans&&point[i]!=)
- {
- ans=point[i];
- }
- }
- printf("%d",ans);
- //fclose(stdin);
- //fclose(stdout);
- return ;
- }
T3 斗地主
题目描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。
现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。
具体规则如下:
输入输出格式
输入格式:
第一行包含用空格隔开的2个正整数T和n,表示手牌的组数以及每组手牌的张数。
接下来T组数据,每组数据n行,每行一个非负整数对aibi表示一张牌,其中ai示牌的数码,bi表示牌的花色,中间用空格隔开。特别的,我们用1来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为02。
输出格式:
共T行,每行一个整数,表示打光第i手牌的最少次数。
输入输出样例
- 1 8
- 7 4
- 8 4
- 9 1
- 10 4
- 11 1
- 5 1
- 1 4
- 1 1
- 3
- 1 17
- 12 3
- 4 3
- 2 3
- 5 4
- 10 2
- 3 3
- 12 2
- 0 1
- 1 3
- 10 1
- 6 2
- 12 1
- 11 3
- 5 2
- 12 4
- 2 2
- 7 2
- 6
说明
样例1说明
共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。
对于不同的测试点, 我们约定手牌组数T与张数n的规模如下:
数据保证:所有的手牌都是随机生成的。
- /*
- dfs中传的step表示出了几个顺子。
- 处理处张数为1~4的牌有多少,存到num数组里
- 搜一下在出step个顺子的情况下将剩下的牌出完要几步,step和这个步数的和就是一个答案,dfs的时候更新答案就好了
- */
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- #define N 25
- using namespace std;
- int T,n,ans;
- int a[N],num[N]; //a放的是牌的大小,num放的是张数分别为1~4的牌的数量
- int chupai()
- {
- memset(num,,sizeof(num));
- for(int i=;i<=;++i) //统计张数为1~4的牌有多少
- ++num[a[i]];
- int tot=;
- while(num[]&&num[]>) //四带二
- {
- --num[];
- num[]-=;
- ++tot;
- }
- while(num[]&&num[]>) //四带一
- {
- --num[];
- num[]-=;
- ++tot;
- }
- while(num[]&&num[]) //把对牌拆成俩单牌用四个带出去
- {
- --num[];
- --num[];
- ++tot;
- }
- while(num[]&&num[]) //三带二
- {
- --num[];
- --num[];
- ++tot;
- }
- while(num[]&&num[]) //三带一
- {
- --num[];
- --num[];
- ++tot;
- }
- return tot+num[]+num[]+num[]+num[]; //出牌次数+剩下的数量
- }
- void dfs(int step) //step==0时,表示不出顺子,step等于几表示出了几个顺子
- {
- if(step>=ans) //剪枝
- return;
- int temp=chupai(); //出牌的次数
- if(temp+step<ans) //更新答案
- ans=temp+step;
- for(int i=;i<=;++i)
- {
- int j=i;
- while(a[j]>=)
- ++j;
- if(j-i>=) //三顺子
- {
- for(int k=i+;k<j;k++)
- {
- for(int l=i;l<=k;l++) //出顺子
- a[l]-=;
- dfs(step+);
- for(int l=i;l<=k;l++) //回溯
- a[l]+=;
- }
- }
- }
- for(int i=;i<=;++i)
- {
- int j=i;
- while(a[j]>=)
- ++j;
- if(j-i>=) //连对
- {
- for(int k=i+;k<j;k++)
- {
- for(int l=i;l<=k;l++) //出顺子
- a[l]-=;
- dfs(step+);
- for(int l=i;l<=k;l++) //回溯
- a[l]+=;
- }
- }
- }
- for(int i=;i<=;++i) //单顺
- {
- int j=i;
- while(a[j]>=)
- ++j;
- if(j-i>=)
- {
- for(int k=i+;k<j;k++)
- {
- for(int l=i;l<=k;l++) //出顺子
- --a[l];
- dfs(step+);
- for(int l=i;l<=k;l++) //回溯
- ++a[l];
- }
- }
- }
- }
- int main()
- {
- scanf("%d%d",&T,&n);
- while(T--)
- {
- memset(a,,sizeof(a));
- for(int i=;i<=n;++i)
- {
- int x,y;
- scanf("%d%d",&x,&y);
- if(x==)
- x=;
- else if(x) x--;
- a[x]++;
- }
- ans=1e9;
- dfs();
- printf("%d\n",ans);
- }
- }
NOIP2015 D1 解题报告的更多相关文章
- 【NOIP2015】提高组D1 解题报告
P1978神奇的幻方 Accepted 描述 幻方是一种很神奇的 N ∗ N 矩阵:它由数字 1,2,3, … … , N ∗ N 构成,且每行.每列及两条对角线上的数字之和都相同. 当 N 为奇数时 ...
- NOIP 2018 D1 解题报告(Day_1)
总分 205分 T1 100分 T2 95分 T3 10分 T1: 题目描述 春春是一名道路工程师,负责铺设一条长度为 nn 的道路. 铺设道路的主要工作是填平下陷的地表.整段道路可以看作是 ...
- NOIP2015 提高组(senior) 解题报告
过了这么久才来发解题报告,蒟蒻实在惭愧 /w\ Day1 T1 [思路] 模拟 [代码] #include<iostream> #include<cstring> #inclu ...
- 【NOIP2015】提高day2解题报告
题目: P1981跳石头 描述 一年一度的“跳石头”比赛又要开始了!这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N ...
- [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告
题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- ZOJ_3950_How Many Nines 解题报告及如何对程序进行测试修改
The 17th Zhejiang University Programming Contest Sponsored by TuSimple Solution: #include <stdio. ...
- ACM-ICPC 2017 Asia HongKong 解题报告
ACM-ICPC 2017 Asia HongKong 解题报告 任意门:https://nanti.jisuanke.com/?kw=ACM-ICPC%202017%20Asia%20HongKon ...
- cf1189解题报告
cf1189div2解题报告 codeforces A 答案要不是一串要不就是去掉最后一个字母的两串 #include <bits/stdc++.h> #define ll long lo ...
随机推荐
- 深度学习Tensorflow相关书籍推荐和PDF下载
深度学习Tensorflow相关书籍推荐和PDF下载 baihualinxin关注 32018.03.28 10:46:16字数 481阅读 22,673 1.机器学习入门经典<统计学习方法&g ...
- 广度优先搜索(BFS)思路及算法分析
1.算法用途: 是一种图像搜索演算法.用于遍历图中的节点,有些类似于树的深度优先遍历.这里唯一的问题是,与树不同,图形可能包含循环,因此我们可能会再次来到同一节点. 2.主要思想: 主要借助一个队列. ...
- .NET子页Main页面实例(UI页面)
<%@ Page Language="C#" MasterPageFile="~/MasterPageDefault.master" AutoEve ...
- NIO开发Http服务器(3):核心配置和Request封装
最近学习了Java NIO技术,觉得不能再去写一些Hello World的学习demo了,而且也不想再像学习IO时那样编写一个控制台(或者带界面)聊天室.我们是做WEB开发的,整天围着tomcat.n ...
- wstngfw中使用虚拟IP映射内网IP
wstngfw中使用虚拟IP映射内网IP -------------------------------- Server01: IP: 192.168.195.73/24 GW: 192.168.19 ...
- kubernetes第十章--ConfigMap 管理配置
- JavaScript 数组去重的那几种方法
数组去重是最常见的面试题,现在总结一下我所知道的几种 首先第一个就是es5 最常见的循环比较 var array= [1, 1, 2]; function test(nums) { for (var ...
- windows下git创建本地分支并建立对应远程分支
在对应项目目录下打开命令提示符 git branch -a 查看所有本地和远程分支 git checkout -b [newBranch] 建立本地分支newBranch git p ...
- JAVA基础之XML相关
个人理解: 知晓XML与HTML的不同,知道其的自由性和约束的方式(规范)!数据按Schema约束写到XML里,然后通过dom4j解析出所有的元素,再用反射创建对象接着调出其所有的方法!!!特别要熟练 ...
- TP5配置隐藏入口index.php文件,Apache/phpstudy
一,找到/public/.htaccess文件,如果你的入口文件已经移动到根目录下,那么你的.htaccess文件也要剪切到根目录下,总之要确保.htaccess跟入口的index.php保持同级. ...