noip2017提高组复赛解题报告

合集下载

noip2017提高组复赛解题报告

noip2017提高组复赛解题报告

noip2017提高组复赛解题报告定期推送帐号信息学新闻,竞赛自主招生,信息学专业知识,信息学疑难解答,融科教育信息学竞赛培训等诸多优质内容的微信平台,欢迎分享文章给你的朋友或者朋友圈!以下解题思路及代码未经官方评测,仅供参考,复赛成绩以官方(CCF)评测结果为准。

Day11.小凯的疑惑(math.cpp/c/pas)【问题描述】小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。

每种金币小凯都有无数个。

在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。

现在小凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在小凯无法准确支付的商品。

【输入格式】输入文件名为math.in。

输入数据仅一行,包含两个正整数a 和b,它们之间用一个空格隔开,表示小凯手中金币的面值。

【输出格式】输出文件名为math.out。

输出文件仅一行,一个正整数N,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。

【输入输出样例1】math.in3 7 math.out11【数据规模与约定】对于30%的数据: 1 ≤a,b ≤50。

对于60%的数据: 1 ≤a,b ≤10,000。

对于100%的数据:1 ≤a,b ≤1,000,000,000。

数学太差只找规律吧。

设:其中一个数为2则:2、3=>1;2、5=>3;2、7=>5;2、11=>9得:2、n=>n-2设:其中一个数为3则:3、5=>7;3、7=>11;3、11=>19;3、13=>23得:3、n=>2n-3设:其中一个数为5则:5、7=>23;5、11=>39;5、13=>47;5、17=>63得:5、n=>4n-5所以:m、n=>(m-1)n-m #includeusing namespace std;int main(){ long long a,m,n;scanf('%lld %lld',&m,&n); a=(m-1)*n-m;printf('%lld',a); return 0;} 2.时间复杂度(complexity.cpp/c/pas)【问题描述】小明正在学习一种新的编程语言A++,刚学会循环语句的他激动地写了好多程序并给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序,于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。

noip2017提高组试题

noip2017提高组试题

CCF 全国信息学奥林匹克联赛(NOIP2017)复赛提高组 day1(请选手务必仔细阅读本页内容)1、文件名(程序名和输入输出文件名)必须使用英文小写。

2、C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。

3、全国统一评测时采用的机器配置为:CPU AMD Athlon(tm) II x2 240 processor,2.8GHz,内存4G,上述时限以此配置为准。

4、只提供Linux 格式附加样例文件。

5、提交的程序代码文件的放置位置请参照各省的具体要求。

6、特别提醒:评测在当前最新公布的NOI Linux 下进行,各语言的编译器版本以其为准。

【问题描述】1.小凯的疑惑(math.cpp/c/pas)小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。

每种金币小凯都有无数个。

在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。

现在小凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在小凯无法准确支付的商品。

【输入格式】输入文件名为math.in。

输入数据仅一行,包含两个正整数a 和b,它们之间用一个空格隔开,表示小凯手中金币的面值。

【输出格式】输出文件名为math.out。

输出文件仅一行,一个正整数N,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。

见选手目录下的math/math1.in 和math/math1.ans。

【输入输出样例1 说明】小凯手中有面值为3 和7 的金币无数个,在不找零的前提下无法准确支付价值为1、2、4、5、8、11 的物品,其中最贵的物品价值为11,比11 贵的物品都能买到,比如:12 = 3 * 4 + 7 * 013 = 3 * 2 + 7 * 114 = 3 * 0 + 7 * 215 = 3 * 5 + 7 * 0……【输入输出样例2】见选手目录下的math/math2.in 和math/math2.ans。

noip2017提高组试题(day1+day2)-Word版

noip2017提高组试题(day1+day2)-Word版

全国信息学奥林匹克联赛(2017)复赛提高组 1(请选手务必仔细阅读本页内容)一.题目概况注意事项:1、文件名(程序名和输入输出文件名)必须使用英文小写。

2、中函数 ()的返回值类型必须是,程序正常结束时的返回值必须是 0。

3、全国统一评测时采用的机器配置为: () x2 240 ,2.8,内存 4G,上述时限以此配置为准。

4、只提供格式附加样例文件。

5、提交的程序代码文件的放置位置请参照各省的具体要求。

6、特别提醒:评测在当前最新公布的下进行,各语言的编译器版本以其为准。

【问题描述】1.小凯的疑惑()小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。

每种金币小凯都有无数个。

在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。

现在小凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在小凯无法准确支付的商品。

【输入格式】输入文件名为。

输入数据仅一行,包含两个正整数 a 和 b,它们之间用一个空格隔开,表示小凯手中金币的面值。

【输出格式】输出文件名为。

输出文件仅一行,一个正整数 N,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。

【输入输出样例 1】见选手目录下的 1 和 1。

【输入输出样例 1 说明】小凯手中有面值为3 和7 的金币无数个,在不找零的前提下无法准确支付价值为1、2、4、5、8、11 的物品,其中最贵的物品价值为 11,比 11 贵的物品都能买到,比如:12 = 3 * 4 + 7 * 013 = 3 * 2 + 7 * 114 = 3 * 0 + 7 * 215 = 3 * 5 + 7 * 0……【输入输出样例 2】见选手目录下的 2 和 2。

【数据规模与约定】对于 30%的数据: 1 ≤ a,b ≤ 50。

对于 60%的数据: 1 ≤ a,b ≤ 10,000。

对于 100%的数据:1 ≤ a,b ≤ 1,000,000,000。

NOIP2017 解题报告 ZYH

NOIP2017  解题报告 ZYH

NOIP2017解题报告一、成绩(score)这是一道送分题。

题目明确规定A、B、C都是10的正数倍。

所以我们可以将读入进来的a、b、c都先整除10,再分别将a*2,b*3,c*5,然后相加,就是最后的答案。

且结果可以保存在longint类型中。

代码如下:vara,b,c,sum:longint;beginassign(input,'score.in');reset(input);assign(output,'score.out');rewrite(output);readln(a,b,c);sum:=a div10*2+b div10*3+c div10*5;writeln(sum);close(input);close(output);end.但倘若题目没有说明A、B、C都是10的正数倍,那么我们就将a*0.2,b*0.3,c*0.5,然后相加。

但这一次结果需存在实型中。

二、图书管理员(librarian)这是一道简单题。

其实吧,本套试卷我们要认真阅读数据规模,总能发现一些微妙的细节。

例如本题,所有的图书编码和需求码均不超过10,000,000完全可以用longint存的(那不就很棒棒了~~)对于读入的每一个需求码,我们都去循环一遍,先判断当前的这本书符不符合需求,但怎么判断呢?数据会告诉我们需求码的长度k,也就是说我们要判断当前书码的后k位是否等于需求码。

哈哈哈,没错,只要用书码mod(10的k次方)即可。

如果相等,那么进行判断取小(因为题目君说要最小的啦~~)。

所以这里如果使用了快排从小到大,那么当你找到第一个满足要求的书码就是答案。

当然不用也可以,时间复杂度为O(nq),1000,000不会炸。

话不多说,代码如下:varn,m,i,j,x,y,sum,min:longint;a:array[0..1000]of longint;procedure f(l,r:longint);varx,y,mid,t:longint;beginx:=l;y:=r;mid:=a[(l+r)div2];repeatwhile a[x]<mid do inc(x);while a[y]>mid do dec(y);if x<=y thenbegint:=a[x];a[x]:=a[y];a[y]:=t;inc(x);dec(y);end;until x>y;if l<y then f(l,y);if x<r then f(x,r);end;beginassign(input,'librarian.in');reset(input);assign(output,'librarian.out');rewrite(output);readln(n,m);for i:=1to n do readln(a[i]);f(1,n);for i:=1to m dobeginreadln(x,y);sum:=1;for j:=1to x do sum:=sum*10;min:=maxlongint;for j:=1to n doif a[j]mod sum=y then begin min:=a[j];break;end;if min=maxlongint then writeln(-1)else writeln(min);end;close(input);close(output);end.但倘若我们的需求码和编码是一些很大很大的数(longint无法承受)时,最最高大上的字符串就闪亮登场了(蹬蹬蹬,天空一声巨响,字符串闪亮登场)。

NOIP提高组复赛题解

NOIP提高组复赛题解

样例 输入: 33 039 285 570 输出: 34 数据规模: 30%的数据满足:1<=m,n<=10 100%的数据满足:1<=m,n<=50
思路: 首先想到搜索,但是对于只考虑一条路线来说, 每一步有两种状态 一共要走m+n步,搜索整棵树的 时间复杂度为O(2^(m+n)),如果两条路线都考虑的 话,时间复杂度为O(4^(m+n)),即使是30%的数据, 即m+n=20,4^20≈10^12,这样的数据规模也还是太 大了。
4维动态规划 本题可以使用动态规划法解决。 设f[i,j,k,l]为第一条线走到(I,j),第二条线走到 (k,l)时的最优值(方便起见,两条线都看作从左上角 开始,右下角结束)。 动态转移方程: f[i-1,j,k-1,l] (i>1) f[i,j,k,l]=min f[i-1,j,k,l-1] (i>1) +s[i,j]+s[k,l] f[i,j-1,k-1,l] (j>1)且(k>i+1) f[I,j-1,k,j-1] (j>1) 同时,由于两条线不能交叉,有k>i。
输入格式: 输入文件matches.in共一行,有一个整数n(n<=24)。 * 输出格式: 输出文件matches.out共一行,表示能拼成的不同等 式的数目。
样例1 输入:
14 输出: 2 解释: 2个等式为0+1=1和1+0=1。
样例2 输入: 18 输出: 9 解释: 9个等式为: 0+4=4、0+11=11、1+10=11、2+2=4、 2+7=9、4+0=4、7+2=9、10+1=11、11+0=11

noip2017普及组复赛解题报告

noip2017普及组复赛解题报告

解法 2 最短路 Dijstra 数据太弱所以用了 dij,数据再强一点的话就需要用邻接表和 spfa 了 (毕竟普及组题难不到哪里去 写的看起来代码看起来很多, 但原理不难 把所有有颜色的点拿出来当做一张新图的结点 初始情况下这些点之间边的长度可以这样判断: 情况 1:如果两点在棋盘上位置相邻,那么同色距离为 0,异色距离为 1(对 应 tryStright 方法) 情况 2 :如果两点在棋盘上位置不相邻但有一个共同相邻的空白点可以做跳 板,使用魔法后同色距离为 2,异色距离为 3(对应 tryIndirect 方法) 然后对这张新图做最短路,求出点(1,1)到其他所有有颜色点的最短路 最后如果(m,m)有颜色, (1,1)到(m,m)之间的距离就是最短路 否则需要借助跳板(m,m-1)或(m-1,m)用魔法到(m,m).
tryIndirectPre(x[i],y[i],x[i]-1,y[i],x[i]-1,y[i]-1); //上上 下下 左左 右右 这些可能通过魔法通过跳板两步到达的点,且跳板唯一 //如原-上-上 情况 2 tryIndirectPre(x[i],y[i],x[i],y[i]+1,x[i],y[i]+2); tryIndirectPre(x[i],y[i],x[i],y[i]-1,x[i],y[i]-2); tryIndirectPre(x[i],y[i],x[i]+1,y[i],x[i]+2,y[i]); tryIndirectPre(x[i],y[i],x[i]-1,y[i],x[i]-2,y[i]); } //直接复制的自己以前写的最短路 dij 模板 //找到点(1,1)到其他所有有颜色的点的最短路 bool hasbeen[1001]; for (i=1;i<=n;i++) hasbeen[i]=false; int pos = abs(chess[1][1]); //棋盘上点(1,1)在新图 path 里是对应的第 pos 个点 for (i=1;i<=n;i++) if (i!=pos) { minPath=10000000; k=1; for ( j=1;j<=n;j++) if ( j!=pos) { if ((hasbeen[ j]==false)&&(path[pos][ j]!=-1)&&(path[pos][ j]<minPath)) { k=j; minPath=path[pos][ j]; } } hasbeen[k]=true; for ( j=1;j<=n;j++) if ( j!=pos) if((path[pos][k]!=-1)&&(path[k][ j]!=-1)) if ((path[pos][ j]>path[pos][k]+path[k][ j])||(path[pos][ j]==-1)) path[pos][ j]=path[pos][k]+path[k][ j]; }

用python解NOIP竞赛题

用python解NOIP竞赛题

⽤python解NOIP竞赛题以下为2017年全国 NOIP 提⾼组复赛的第1题:怎么样,读完题是不是感觉特别懵。

—— 我是谁,我在哪⾥?接下来我们来慢慢解析这道让⼈摸不着头脑的竞赛题。

⼀、⾸先翻译⼀下题的意思:假设,现在⼈民币只有两个币种,⾯值你定对⾯值数字的要求是这两个数字不能有公约数(除1这个公约数外)当然,前提是你有任意多的钱是不是稍微要清晰⼀些了呢。

⼆、那我们接下来⽤python写⼀个程序来完成这道题:整个过程分两步:第⼀步:借助 python 找规律划范围1# 先找出能凑出来的⾦额2def myFunc(a, b): # 输⼊a,b 两个互素的⾯值3 c = 1 # 从1开始找出能凑出的⾦额4while True: # 不断循环,电脑配置低的,请远离,前⽅危险5for i in range(c):6 an01 = a * i7for j in range(c):8 an02 = b * j9if an01 + an02 == c: # ⼀旦找到能凑出当前⾦额c的i和j,打印出来10# print(c, "=", a, '*', i, '+', b, '*', j)11print(c,end='')12 c += 1 # ⾦额不断上涨,上不封顶131415if__name__ == "__main__":16 myFunc(3, 5)结果为:如果将⾯值设置为 7,5 呢结果:再如果换成 7,9结果:综上:我们可以发现,不可组合的⾯值均集中在靠前的位置,但有多靠前,具体⼜在哪个位置呢?我们姑且假定这个数字就在两数的乘积之内,⽽且事实也是这样的。

⼤家可以多试⼏对数字,检验⼀下。

第⼆步:范围找到后,我们再来考虑⽤ python 找出范围内的不可组合的⾦额值: 备注:上⾯的程序是⼀个死循环,需要⼿动结束程序,建议不懂操作的⼩伙伴谨慎运⾏(嘿嘿,你是不是已经⼊坑啦!)。

【精选资料】NOIP提高组复赛试题与简解转载

【精选资料】NOIP提高组复赛试题与简解转载

Day1铺地毯【问题描述】为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。

一共有n 张地毯,编号从1 到n。

现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。

地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。

注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。

【输入】输入文件名为 carpet.in。

输入共 n+2 行。

第一行,一个整数 n,表示总共有n 张地毯。

接下来的 n 行中,第i+1 行表示编号i 的地毯的信息,包含四个正整数a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a,b)以及地毯在x轴和y 轴方向的长度。

第 n+2 行包含两个正整数x 和y,表示所求的地面的点的坐标(x,y)。

【输出】输出文件名为 carpet.out。

输出共 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1。

【输入输出样例 1】【输入输出样例说明】如下图,1 号地毯用实线表示,2 号地毯用虚线表示,3 号用双实线表示,覆盖点(2,2)的最上面一张地毯是3 号地毯。

【输入输出样例 2】【输入输出样例说明】如上图,1 号地毯用实线表示,2 号地毯用虚线表示,3 号用双实线表示,点(4,5)没有被地毯覆盖,所以输出-1。

【数据范围】对于 30%的数据,有n≤2;对于 50%的数据,0≤a, b, g, k≤100;对于 100%的数据,有0≤n≤10,000,0≤a, b, g, k≤100,000。

【一句话题意】给定n个按顺序覆盖的矩形,求某个点最上方的矩形编号。

【考察知识点】枚举【思路】好吧我承认看到图片的一瞬间想到过二维树状数组和二维线段树。

置答案ans=-1,按顺序枚举所有矩形,如果点在矩形内则更新ans。

注意题中给出的不是对角坐标,实际上是(a,b)与(a+g,b+k)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

noip2017提高组复赛解题报告定期推送帐号信息学新闻,竞赛自主招生,信息学专业知识,信息学疑难解答,融科教育信息学竞赛培训等诸多优质内容的微信平台,欢迎分享文章给你的朋友或者朋友圈!以下解题思路及代码未经官方评测,仅供参考,复赛成绩以官方(CCF)评测结果为准。

Day11.小凯的疑惑(math.cpp/c/pas)【问题描述】小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。

每种金币小凯都有无数个。

在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。

现在小凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在小凯无法准确支付的商品。

【输入格式】输入文件名为math.in。

输入数据仅一行,包含两个正整数 a 和b,它们之间用一个空格隔开,表示小凯手中金币的面值。

【输出格式】输出文件名为math.out。

输出文件仅一行,一个正整数N,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。

【输入输出样例1】math.in3 7 math.out11【数据规模与约定】对于30%的数据: 1 ≤a,b ≤50。

对于60%的数据: 1 ≤a,b ≤10,000。

对于100%的数据:1 ≤a,b ≤1,000,000,000。

数学太差只找规律吧。

设:其中一个数为2则:2、3=>1;2、5=>3;2、7=>5;2、11=>9得:2、n=>n-2设:其中一个数为3则:3、5=>7;3、7=>11;3、11=>19;3、13=>23得:3、n=>2n-3设:其中一个数为5则:5、7=>23;5、11=>39;5、13=>47;5、17=>63得:5、n=>4n-5所以:m、n=>(m-1)n-m #includeusing namespace std;int main(){ long long a,m,n;scanf('%lld %lld',&m,&n); a=(m-1)*n-m; printf('%lld',a); return 0;} 2.时间复杂度(complexity.cpp/c/pas)【问题描述】小明正在学习一种新的编程语言A++,刚学会循环语句的他激动地写了好多程序并给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序,于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。

A++语言的循环结构如下:其中“F i x y”表示新建变量(i 变量i 不可与未被销毁的变量重名)并初始化为x,然后判断i 和y 的大小关系,若i 小于等于y 则进入循环,否则不进入。

每次循环结束后i都会被修改成i +1,一旦i 大于y 终止循环。

x和y 可以是正整数(x 和y 的大小关系不定)或变量n。

n 是一个表示数据规模的变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于100。

“E”表示循环体结束。

循环体结束时,这个循环体新建的变量也被销毁。

注:本题中为了书写方便,在描述复杂度时,使用大写英文字母“O”表示通常意义下“Θ”的概念。

【输入格式】输入文件名为complexity.in。

输入文件第一行一个正整数t,表示有t(t ≤10)个程序需要计算时间复杂度。

每个程序我们只需抽取其中“F i x y”和“E”即可计算时间复杂度。

注意:循环结构允许嵌套。

接下来每个程序的第一行包含一个正整数L 和一个字符串,L 代表程序行数,字符串表示这个程序的复杂度,“O(1)”表示常数复杂度,“O(n^w)”表示复杂度为n^w,其中w 是一个小于100 的正整数(输入中不包含引号),输入保证复杂度只有O(1)和O(n^w) 两种类型。

接下来L 行代表程序中循环结构中的“F i x y”或者“E”。

程序行若以“F”开头,表示进入一个循环,之后有空格分离的三个字符(串)i x y,其中i 是一个小写字母(保证不为“n”),表示新建的变量名,x 和y 可能是正整数或n ,已知若为正整数则一定小于100。

程序行若以“E”开头,则表示循环体结束。

【输出格式】输出文件名为complexity.out。

输出文件共t 行,对应输入的t 个程序,每行输出“Yes”或“No”或者“ERR”(输出中不包含引号),若程序实际复杂度与输入给出的复杂度一致则输出“Yes”,不一致则输出“No”,若程序有语法错误(其中语法错误只有: F 和E 不匹配;新建的变量与已经存在但未被销毁的变量重复两种情况),则输出“ERR”。

注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出“ERR”。

【输入输出样例1】complexity.in82 O(1)F i 1 1E2 O(n^1)F x 1 nE1 O(1)F x 1 n4 O(n^2)F x 5 nF y 10 nEE4O(n^2)F x 9 nEF y 2 nE4 O(n^1)F x 9 nF y n 4EE4 O(1)F y n 4F x 9 nEE4 O(n^2)F x 1 nF x 110EEcomplexity.outYesYesERRYesNoYesYesERR【数据规模与约定】对于30%的数据:不存在语法错误,数据保证小明给出的每个程序的前L/2 行一定为以 F 开头的语句,第L/2+1 行至第L 行一定为以 E 开头的语句,L,若x、y 均为整数,x 一定小于y,且只有y 有可能为n。

对于50%的数据:不存在语法错误,L,且若x、y均为整数,x 一定小于y,且只有y 有可能为n。

对于70%的数据:不存在语法错误,L。

对于100%的数据:L。

用STL stack模拟,对于用代码量堆出来的OIer来说,这就是信心倍增的大力模拟题。

代码就不上了。

3. 逛公园(park.cpp/c/pas)【问题描述】策策同学特别喜欢逛公园。

公园可以看成一张N个点M条边构成的有向图,且没有自环和重边。

其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的时间。

策策每天都会去逛公园,他总是从1号点进去,从N号点出来。

策策喜欢新鲜的事物,他不希望有两天逛公园的路线完全一样,同时策策还是一个特别热爱学习的好孩子,他不希望每天在逛公园这件事上花费太多的时间。

如果1号点到N号点的最短路长为d,那么策策只会喜欢长度不超过d+K的路线。

策策同学想知道总共有多少条满足条件的路线,你能帮帮他吗?为避免输出过大,答案对P取模。

如果有无穷多条合法的路线,请输出?1。

【输入格式】输入文件名为park.in。

第一行包含一个整数T, 代表数据组数。

接下来T组数据,对于每组数据:第一行包含四个整数N, M, K, P,每两个整数之间用一个空格隔开。

接下来M行,每行三个整数ai , bi , ci,代表编号为ai, bi的点之间有一条权值为ci的有向边,每两个整数之间用一个空格隔开。

【输出格式】输出文件名为park.out。

输出文件包含T行,每行一个整数代表答案。

【输入输出样例1】park.in25 7 2 101 2 12 4 04 5 22 3 23 4 13 5 21 5 32 2 0 101 2 02 10park.out3-1【数据规模与约定】对于不同的测试点,我们约定各种参数的规模不会超过如下:对于100%的数据, 1≤P≤109,1≤ai,bi≤??,0≤ci ≤1000。

数据保证:至少存在一条合法的路线。

最短路+拓扑排序+DP先跑最短路。

发现K只有50,所以一定是要从K入手。

所以考虑DP,令f[i][j]表示走到i,多走的长度是j的方案数。

(多走指的是比最短路多的部分的长度)。

但是发现这个DP方程是存在环的,因为最短路径图上的边以及零边都是可以同行转移的。

将最短路径图上的边以及零边都拿出来跑拓扑排序,然后让这些边在转移时必须沿着拓扑序转移即可。

特别地,如果一个零环位于一条从1到n长度的路径上,则输出-1即可。

#include#include#include#include#include#include#define mp(A,B)make_pair(A,B)using namespace std;const int maxn=100010;const intmaxm=200010;int n,m,cnt,K,P,tot,ans;intto[maxm],next[maxm],val[maxm],head[maxn],dis[maxn],vis[maxn],d[maxn],q[ maxnintto2[maxm],next2[maxm],val2[maxm],head2[maxn],dis2[maxn];priority_queue > pq;inline int rd(){ int ret=0; char gc=getchar(); while(gc'9')gc=getchar(); while(gc>='0'&&gc return ret;}inline void add(int a,int b,int c){ to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt;to2[cnt]=a,val2[cnt]=c,next2[cnt]=head2[b],head2[b]=cnt++;}inline voidupd(int &x,int y){ x=(x+y)%P;}void work(){ n=rd(),m=rd(),K=rd(),P=rd(); int i,j,k,a,b,c,u;memset(head,-1,sizeof(head)),memset(head2,-1,sizeof(head2)),cnt=tot=ans=0; for(i=1;i //1memset(vis,0,sizeof(vis)),memset(dis,0x3f,sizeof(dis)),memset(d,0,sizeof(d)); pq.push(mp(0,1)),dis[1]=0; while(!pq.empty()){ u=pq.top().second,pq.pop(); if(vis[u]) continue;vis[u]=1; for(i=head[u];i!=-1;i=next[i])if(dis[to[i]]>dis[u]+val[i])dis[to[i]]=dis[u]+val[i],pq.push(mp(-dis[to[i]],to[i]));} //2 memset(dis2,0x3f,sizeof(dis2)),memset(vis,0,sizeof(vis));pq.push(mp(0,n)),dis2[n]=0; while(!pq.empty()){ u=pq.top().second,pq.pop(); if(vis[u]) continue;vis[u]=1; for(i=head2[u];i!=-1;i=next2[i])if(dis2[to2[i]]>dis2[u]+val2[i])dis2[to2[i]]=dis2[u]+val2[i],pq.push(mp(-dis2[to2 [i]],to2[i])); } //3 for(i=1;i for(i=1;i for(j=1;j{ u=q[j]; for(i=head[u];i!=-1;i=next[i])if(dis[u]+val[i]==dis[to[i]]) { d[to[i]]--;if(!d[to[i]]) q[++tot]=to[i]; } } for(i=1;i{ printf('-1\n'); return ; } //DPmemset(f,0,sizeof(f)); f[0][1]=1; for(k=0;k { for(i=1;i { upd(f[k][to[j]],f[k][u]); } for(i=1;i{ upd(f[k+dis[i]+val[j]-dis[to[j]]][to[j]],f[k][i]); } }for(i=0;i printf('%d\n',ans);}int main(){ int T=rd(); while(T--)work(); return 0;}Day2 1.奶酪(cheese.cpp/c/pas)【问题描述】现有一块大奶酪,它的高度为h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞。

相关文档
最新文档