Loading...

Archive

Posts Tagged ‘NOIp’

NOIp 2009 解题报告

November 26th, 2009 8 comments

以下是我的NOIp 2009 (提高组) 解题报告.

第一题(潜伏者, spy): 略.

第二题(Hankson 的趣味题, son):

Gcd(x,a0)=a1, Gcd(x,b0)=xb0/b1

设f(a,b) 代表b这个质因子在a中有多少个.

对于a0的任意质因子t, 若f(a0,t)=f(a1,t) 则只需保证f(x,t)≥f(a1,t), 否则f(x,t)=f(a1,t)

对于b1的任意质因子t, 若f(b1,t)=f(b0,t) 则只需保证0≤f(x,t)≤f(b1,t), 否则f(x,t)=f(b1,t)

由于x的所有因子都是b1的子集, 所以我们只需对b1的质因子按如上方法逐个检查这个质因子在x里面的取值范围(若为空则说明无解), 并按照乘法原理统计即可.

关于分解质因子: 由于b1不会超过2*10^9, 大于50000的质因子不会超过1个, 所以我们只要打出50000以内的素数表即可, 若最后除剩的b1仍未除尽, 说明此时b1一定是一个大于50000的素数.

第三题(最优贸易, trade):

做法1:

设Low[i]为从1到i当前所有路径中最便宜的价格. Profit[i]为从1到i当前所有路径中最大获利. 初始时Low[1]=P[1], Low[2..n]=infinity, Profit[1..n]=0.

那么我们可以从1开始广搜, 要注意一个点有可能多次被更新.

从i可以更新到j的条件是:

1. 存在有向/无向边(i,j)

2. Low[j]>Low[i] 或 Profit[j]<Profit[i]

做法2:

首先考虑没有环的情况, 此时1,n之间要么无法连通, 要么只存在一些单向的无环路径. 对于每一条路径, 由于不能”回头”, 走到某个点i的极优获利显然是i的费用-路径上此点之前的点的最小费用, 而此路径的最大获利便是取获利最大的点.

但是还有很多数据是有环的, 也就是对于有些点对(a,b), 在a走到b之后, b仍然可以走回到a. 在图论中, 我们把点集V, 其中任意两个点可以互达, 叫做强连通分量.

由于强连通分量中的点可以互相到达, 所以在一个强连通中的最大获利就是强连通中最贵的-最便宜的. 我们把所有强连通分量求出来缩为两个点之后. 1与n之间只存在一些无环路径, 对于这些单向的无环路径我们只需要扫描一遍便可求出最大获利.

强连通缩为两个点的具体做法: 把一个强连通缩为a,b 两个点, 连(a,b)边, a的费用为强连通中最便宜的, b的费用为强连通中最贵的. 把指向强连通中任何一个点的所有边改为指向a, 把强连通中任何一点指向强连通外部的边改为由b指出. 这样构出来的保证与原图等价.

第四题(靶形数独, sudoku): 很直白的搜索, 由于数独是NP-H问题, 所以我们肯定只能用搜索, 那么关键就在于剪枝了, 我们发现, 对于每个格子都有一个取值范围, 这个范围由其横行/纵行/小九宫格中已填的数决定, 那么无疑我们每次搜索选取值范围最小的格子搜是比较优的.

Categories: Informatics Tags: ,

CCF 是对的 — 一个信息学竞赛选手的自白

January 28th, 2009 10 comments

前几天,在2009年全国信息学竞赛冬令营中,CCF 的杜秘书长提出了近期要取消 NOIp (全国信息学竞赛分区联赛)的一等奖保送资格,取而代之的是高考加分。有些人就不高兴了,我在冬令营的寝室里就经常听到众多选手的埋怨。接下来,CCF 的网站被黑了,大概也是这个原因。还有就是 cnBeta 里发的这一篇《论NOIP取消保送与CCF被黑——NOIP选手自白》。

Read more…

Categories: Trivia Tags:

长郡NOIp2008停课集训试题解题报告&测试数据 – 10月28日

October 28th, 2008 1 comment

测试数据和完整解题报告在此下载: DropBox | Skydrive

正文:

10月28日_G122_cnPhil_的解题报告

先看哈:

选手列表

编号 姓名 总分

02.mt 02.mt 400.00

standard standard 400.00

–测试器上一角,Orz mt大牛。

简单题目

Easy

时间限制:1s

空间限制:128M

【题目背景】

经典题目自有经典算法。

 

【题目描述】

给你一个N*MN,M<=1000)的01矩形,求一个面积最大的不包含数字1的矩形。

 

【输入数据】

第一行两个数NM

接下来N行,每行M个数为01

 

【输出数据】

一个数ans表示最大空矩形的面积。

Sample

Easy.in

2 4

1 0 0 0

0 1 1 0

 

Easy.out

3

Solve:

这道题,我是用类动规方法做的。对于一个点,记录其竖直向上、水平向左两条最大可以达到多长,再根据这个点左边、上面的点的值求出以这个点为右下角的矩形最大能达到多少。mlj的方法:枚举每列,求出每两个1或边界之间的最大可取矩形。(预处理时标记每点最左最右双向可取长度)

SB

SB

时间限制:1s

空间限制:128M

【题目背景】

题如其名啦……

【题目描述】

给你一棵NN<=10000)个节点的树,求每个点到其他点的最大距离。

【输入数据】

第一行一个数N

接下来若干行每行两个数kt描述一条点k到点t的边(输入数据保证无重复边)。

【输出数据】

N行每行一个数表示每个点到其他点的最大距离。

Sample

SB.in

5

1 2

1 3

1 4

4 5

SB.out

2

3

3

2

3

Solve:

这道题,有个两遍深搜的方法:首先对于每个点,先构造树结构(任选一点作为根),回溯时求出它到底层的最长路和次长路,然后再对于每个点i,枚举这个点到根的每个点j,若这一段ij不在j的最长路上,那么用ij长+j的最长路更新i点值,若这一段ij在j的最长路上,那么用ij长+j的次长路更新i点值。另外还有一个树形动规的方法,貌似很难实现:从底层到根,一层一层来,对于一条边u,v,求出去除其后,以u为根,最长的一条 路径(有边就是路,不管是子是父)就等于u连出的边的目标点的最长路径值,然后对v为根也做一遍。最后,加一个废点指向根,求出经过根的最长路径。这个方法被指有误!不知道是我听错了还是怎么地。哪位大牛能给我讲讲这个树形动规的方法?

判断

Compare

时间限制:1s

空间限制:128M

【题目背景】

这不是道水题!这真的不是道水题!这绝对不是道水题!!!

【题目描述】

给你一个n(n<=1000)个点m(m<=n*n-1/2)条边的图和k(k<=100)程序对这个图做从点1到点n的最短路后得到的的结果,写一个compare判断谁的输出最优。

【输入数据】

第一行三个数nmk

接下来m行,每行三个数abdata表示点a到点b有一条长度为data的无向边(任意两点间最多只有一条边)。

接下来k行,每行为一个程序得到的路径方案(保证路径方案的长度不超过2000)

【输出数据】

如果所有输出均不合法,输出’Wrong‘,否则输出一个保留4位小数的实数,表示k个人得出结果中最小的一条合法路径长度。

Sample

Compare.in

3 3 4

1 2 5.2000

2 3 3.5000

3 2 6.0000

1 2 3 2 3 2 3 2 3 2 3 2 3

1 2 2 3 3 3

1 3

1 3 2 3

Compare.out

8.7000

Solve:

我觉得这道题目内容和上一道题的标题很配。

最优序列

Best

时间限制:1s

空间限制:128M

【题目背景】

背景的意义就是没人看得懂……

题目的意义就是没人做得出……

【题目描述】

给出一个长度为n(n<=1000) 的正整数序列,求一个子序列,使得原序列中任意长度为m 的子串中被选出的元素不超过k(k<=m<=10) 个,并且选出的元素之和最大。

【输入数据】

第一行三个数n,m,k 

第二行n 个数,表示各元素数值大小。

【输出数据】

一个数,表示最大元素和。

Sample:

Best.in

10 4 2

7 3 4 8 2 6 5 7 4 8

Best.out

36

Solve:

与其说是动规,还不如说是搜索。以一个二进制串表示状态情况,然后考虑第i个取不取时,若第i-m个状态值为0,那么这个i状态值一定为0,否则枚举0,1。冷吧!

Categories: Informatics Tags: ,

长郡NOIp2008停课集训测试解题报告 – 10月27日

October 27th, 2008 8 comments

呃,今天电脑有点卡。

测试数据和解题报告完整版在这里下载:DropBox, Skydrive

正文:

老师的询问
题目描述:

东汉末年,颖川书院,有一日老夫子给他的学生出了一道问题,书院中有一口清澈见底的池塘(什么都看得见),老夫子要吃鱼,池塘里有很多很多鱼,而池塘是一个n*m的矩形,他希望放置最少的挡板,将池塘分成很多个矩形(包括正方形),使得每个矩形里有且只有一条鱼,而作为老夫子学生的郭嘉很想完成这个任务,所以他把这个任务交给了你,他相信作为长郡中学未来希望的你肯定不差,希望你能很快地解决问题。

例如:
  n=4m=3时的一种情况(0表示小方格内无鱼,1表示有鱼)。
0 1 0
0 0 0
1 0 1
0 0 0
  可以这么分:

0 1 0

0 0 0

——
1|0 1
0|0 0
  由于池塘边框不需要放置挡板,所以这个分割方案所需的挡板总长度为5
输入数据:
第一行有两个整数nm1n,m32),描述池塘规模。接下来的n行,每行有m个数字(非“0”即“1”)。每两个数字之间用空格隔开。

输出数据:
对于每组输入数据,输出一行:一个数字,所需挡板的最短总长度。

输入样例:
4 3

0 1 0
0 0 0

1 0 1
0 0 0

输出样例:
5

Solve:

    这一道题mt大牛说用类A*算法,先广搜(枚举每条鱼的矩形),检验状态重复,然后用貌似很不必要的方法剪枝。

袁绍的刁难

题目描述:

黄巾之乱后,郭嘉到了袁绍的统辖地区,结果袁绍想给我们的郭嘉大大一个下马威,且正值他招募将领的时候,于是乎,袁绍就让郭嘉大大去替他招募将领。
  这时候有很多很多的将领到袁绍处报到(别人家底厚,四世三公哪~~),每个将领的编号依次为123……N,第i个将领的武力值为3^(i-1)
  袁绍需要我们的郭嘉大大招纳任意个将领,而郭嘉选中的将领有一个“总武力值”为各个将领的武力值之和。例如:郭嘉这一次招募了第一个将领和第三个将领,那么“总武力值”为1+9=10
  袁绍想知道,他可以获得的第k小的“总武力值”是多少,请你帮助我们的郭嘉大大告诉袁绍这个第k大的“总武力值”。
  从文件中读入k,输出郭嘉能够获得的,第k大的“总武力值”。

输入:
  数据包含n+1行,第一行读入n(n100)。以下n行每行包含一个k

输出:
  输出包含n行,每行输出一个对应的结果。 

输入样例:
1
7

输出样例:
13

样例说明:
  郭嘉能够拿到的总武力值从小到大为1349101213……所以第7小的总武力值是13
  对于50%的输入文件,有k5000
  对于100%的输入文件,有k2^31-1
Solve:

这道题是很典型的数学归纳题,类似NOIp2006普及组的第三题,把每一个k请求转成2进制,再把这个二进制数乘以三进制的位权(101=>1*3^2+0*3^1+1*3^0),这样就是结果。这是应用排列组合的方法。自己多模拟模拟就可以发现规律。

游历的路线

题目描述:

    我们的郭嘉大大经过一段时间发现了袁绍这个人干大事而惜身,见小利而忘义,又逢曹操在招兵买马,决定逃离袁绍去投曹操,而我们的曹操在第M天招募良材,我们的郭嘉大大既不能早去,也不能晚去,于是乎,他就趁着这一段时间到其他的城市游历一番,而每两个城市之间只能坐马车来往,由于我们的郭嘉大大很贪钱,他想用最少的费用,所以需要我们帮他求出这一个最小的费用。

输入:

第一行包含两个数nm, 表示有n个城市,和m天后曹操招纳良材。城市一就是郭嘉所在的城市,城市n就是曹操处。接下来n * (n – 1)行描述马车乘坐表。第2到第n行就是描述的城市12… n的马车乘坐表,第n + 1到第2n-1行描述的城市2到城市13..n的马车乘坐表… … 对每一行,首先有一个数T,表示城市I到城市J的马车以T为周期,接下来有T个数,表示每天的马车的价格,如果价格为0则表示没有马车可坐。

n <= 100,  m <= 200,  T <= 20 Price <= 50000
输出:

如果存在这样的路线使郭嘉第m天到达曹操处,则输出最少的费用,否则输出0

输入样例:                             

3 5                                       

2 130 150

3 75 0 80

2 110 100

4 60 70 60 50

3 0 135 140

2 70 80

输出样例:

355

Solve:

    F[i,j]表示第i天到第j个城市的最小花费,

    则有:F[i,j]=Min{F[i-1,k]+Effort(i-1,k,j)}  1<=k<=n

    F[n,m]即为所求。

消息的传递

题目描述:

我们的郭嘉大大在曹操这过得逍遥自在,但是有一天曹操给了他一个任务,在建邺城内有N<=1000)个袁绍的奸细,将他们从1N进行编号,同时他们之间存在一种传递关系,即若C[ij]=1,则奸细i能将消息直接传递给奸细j

现在曹操要发布一个假消息,需要传达给所有奸细,而我们的郭嘉大大则需要传递给尽量少的奸细使所有的奸细都知道这一个消息,问我们至少要传给几个奸细

输入:

    文件的第一行为N,第二行至第N+1行为N*N的矩阵(若第I行第J列为1,则奸细I能将消息直接传递给奸细J,若第I行第J列为0,则奸细I不能将消息直接传递给奸细J)。

输出:

    输出文件只有一行:即我们的郭嘉大大首先至少要传递的奸细个数。

 

输入样例:                             

8

0 0 1 0 0 0 0 0 

1 0 0 1 0 0 0 0 

0 1 0 1 1 0 0 0 

0 0 0 0 0 1 0 0 

0 0 0 1 0 0 0 0 

0 0 0 1 0 0 0 0 

0 0 0 1 0 0 0 1

0 0 0 0 0 0 1 0

输出样例:

2

Solve:

    很经典的图论题目哦。

    首先,求出图中所有强连通分量(Strongly Connected Component, SCC),然后把每个强连通分量缩为一个“点,此时原图就变成了一个标准的拓扑图。入度为0的“点”即为所求。

    强连通分量的求法:(这里给出刘铮同学的求出一个点所在的强连通分量的过程)

procedure zuo(r:longint);

var

  i,j,q:longint;

begin

  inc(p);  //建栈

  b[p]:=r;//r点入栈

  a[r]:=p;//r点在栈中的位置

  c[r]:=p;//r点能连出的最前的点,初值为自己。(link

  i:=v3[r];//选边集数组中r出的一条边。

  while i<>0 do begin

    j:=v1[i];//得到当前边的目标结点

    if(d[j]=0)then begin//如果j点当前不属于任何强连通分量

      if a[j]=0 then zuo(j);//并且j没有进栈,则求j的强连通分量

      if(c[j]<c[r])and(a[j]<>0) then c[r]:=c[j];//jlink值在r之前,且j未出栈,则更新link

    end;

    i:=v2[i];//下一条r出的边

  end;

  if c[r]=a[r] then begin//r不能连到前面,则rr栈以后的点全部出栈。

      q:=a[r];

      for i:=a[r] to p do begin

        d[b[i]]:=r;

        a[b[i]]:=0;

        c[b[i]]:=0;

      end;

      p:=q-1;

  end;

end;

Categories: Informatics Tags: ,

NOIp 模拟测试解题报告(1)

September 20th, 2008 1 comment

第一题:给出一串已经拓扑好了的事件,求最短完成时间。

做滥了的题目啊,直接扫一边就出解,O(n)

 

第二题:给出第二周的歌曲排行榜和每首歌的歌曲排名变化(上升、下降、持平),求前一周的歌曲排行榜的一种可能解。

字符串处理的题目;

首先,我们把上升了的歌看作要把它往下移,而下降了的歌呢就看作要把它往上移,再把所有的持平歌去掉

那么,现在的排行榜的首位肯定是下,而末位肯定是上了。

现在,找所有下一位是上的下节点。从这个下节点往上延伸到所有连着的下节点,而从这个上节点往下延伸到所有连着的上节点,把这两个模块互换即可。

第三题:你向银行贷款,告诉你你的贷款额、每月还款额和还款月数。求每个月的月利率(每个月银行先算利再让你还钱)

初以为这道题目十分简单,发现不然,这个题目列出来是个高次方程。其实是可以用log函数来解,但是对于有未知数的log函数,Pascal语言显得十分麻烦(几乎不可能实现)。所以,我在考试的时候使用了枚举的方法,得了60%的点。

但是我竟然忘记了世上有二分这样的好方法,其实,以你的总还款额/贷款额的利率(这个是绝对不可能达到的)为上界,下界为0,来二分求解,效果很好。但是虽然二分时间不超,但是发现有一个点竟然超过了int64和extended的届,呵呵。

第四题:走迷宫变形,有起始朝向,就是一秒钟内可以走1格、2格、3格,而且向左向右转也要耗费一秒。

爆容易的题目,难得写了。只有50×50的大小,不说广搜,深搜都能过啊。

课后孟LJ简单阐述了下搜索的优化,无非以下三种:

1、双向广搜(省时一半,较容易实现);

2、普通判断剪枝(子树);

3、估价函数剪枝(A*)。这种做法需要良好的估价能力,适合要打路径的题目。估价函数是一个可以求出从当前状态到目标状态的大概花费的函数,其值必须小于等于真实花费。所以,当走到一个(当前花费+估价花费>已知最小花费)的点时,完全可以把他的子树剪掉。这就是一种动态剪枝方法。效果甚佳,但本人未实现。

Categories: Trivia Tags: ,

NOIp 2000 提高组解题报告

September 9th, 2008 No comments

题一   进制转换:

负进制,短除法,但是余数小于0时要从上一位借位(商+1,余数-进制数)(LRJ大牛提出)

 

题二   乘积最大:

动规+递归

设d(i,j,k)为第i-j个数字中用k个乘号所取得的最大乘积。

转移方程(我直接用递归调用 ^_^):

d(i,j,k)=max{数(第i到第t个字)*d(t,j,k-1)}   (i<=t<=j-1)

临界:所有k=0的值就为原来的值。

 

题三   单词接龙:

求出一张表示每两个单词(有序)之间的增长字母数的表,根据这张表枚举第一个单词来搜。居然全不超时。但是发现有的单词可以用两遍,囧。

 

题四   方格取数:

一直没想通。LRJ的报告太草了。飞机的报告里面是“广搜式Dp,效率还不错。可能数据比较弱。”,囧;

Google了一下,发现“上帝的右手”大牛的报告不错:

两条路线同时进行的动态规划

阶段:按所走的步数来分阶段,从左上角走到右下角,共2n-1个步骤,故共2n-1个阶段。但,有两条线路,故每一阶段的状态都会复杂一些。

状态:有两线路同时走,在某阶段的某状态,要用两个坐标来分别表示两线路的两个点。如:第一阶段,共一个状态:(1,1),(1,1);第二阶段,(1,2),(1,2);(1,2),(2,1);(2,1),(1,2);(2,1),(2,1)共四个状态。

  由于在第k阶段的任何两个点的x,y坐标是有关系的:k+1=x+y。故可只用x坐标来表示一点的坐标,故状态可表示为(x1,x2),对应的y坐标为:y1=k+1-x1,y2=k+1-x2。

决策:若用0,1分别表示向下或向右走,则每个状态的可能决策有四种:(1,1),(0,0),(1,0),(0,1)。两个数值分别表示两个点的下一步走向。

状态转移方程:

  设map(x,y)为方格图,f(k,x1,x2)表示第k个阶段走到(x1,x2)状态的最大和

  f(0,1,1)=map(x1,1+1-x1) 即map(1,1)

  f(k,x1,x2)=max{f(k-1,x1′,x2′)+map(x1,y1)|x1=x2,f(k-1,x1′,x2′)+map(x1,y1)+map(x2,y2)|x1<>x2} (x1′,x2′)表示可通过某决策到达(x1,x2)的所有点

 

明天再把第四题实现一下,就要进入恐怖的2001后了。。。

Categories: Trivia Tags: