昨天就是洛谷三月月赛,小编考的并不好,才31分,隔壁大佬50分,于是小编决定改一改题,先看第一题:

                  P5238 整数校验器

题目描述

有些时候需要解决这样一类问题:判断一个数 x 是否合法。

x 合法当且仅当其满足如下条件:

  • x 格式合法,一个格式合法的整数要么是 0,要么由一个可加可不加的负号,一个 1 到 9 之间的数字,和若干个 0 到 9 之间的数字依次连接而成。
  • x 在区间 [l,r][l,r] 范围内(即 l≤x≤r)。

你需要实现这样一个校验器,对于给定的 l,r,多次判断 x 是否合法。

输入输出格式

输入格式:

第一行三个整数 T,l,r,表示校验器的校验区间为 [l,r][l,r],以及需要校验的 x 的个数。

接下来 T 行,每行一个x,表示要校验的数,保证 x 长度至少为 1 且仅由 '0'~'9' 及 '-' 构成,且 '-' 只会出现在第一个字符。

输出格式:

输出共 T 行,每行一个整数,表示每个 xx 的校验结果。

校验结果规定如下:0 表示 x 合法;1 表示 x 格式不合法;2 表示 x 格式合法且不在 [l,r] 区间内。

输入输出样例

输入样例#1: 复制

-3 3 4
0
00
-0
100000000000000000000

输出样例#1: 复制

0
1
1
2

  这道题一看很有思路,不就是输入字符串,在多判断几次,代码很快就出来了。

 1 // luogu-judger-enable-o2
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std;
 5 char c[1000000000];long long T,l,r,cnt,sum,k;bool flag;char x;
 6 int main()
 7 {
 8     scanf("%lld%lld%lld",&l,&r,&T);
 9     x=getchar();
10     for(int i=1;i<=T;i++)
11     {
12         //x=getchar();
13         cnt=0;sum=0;flag=false;k=0;
14         for(;;)
15         {
16             c[++cnt]=getchar();//cout<<"1:"<<cnt<<" "<<c[cnt]<<endl;
17             //cout<<c[cnt]<<" "<<sum<<endl;
18             if(c[cnt]=='-') sum=0-sum;
19             else if(c[cnt]=='\n') break;
20             else
21             {
22                 sum*=10;sum+=(c[cnt]-48);
23             }
24
25         }
26 //        for(int j=1;j<=cnt;j++)
27 //        cout<<c[j];
28 //        cout<<endl;
29         //cout<<"1:"<<cnt<<" "<<sum<<endl;
30         for(int j=1;j<=cnt;j++)
31         {
32
33
34              if(c[j]=='0'&&cnt>2&&j==1)
35             {
36                 //cout<<"c["<<j<<"]=='0'&&"<<cnt<<">2"<<endl;
37                 printf("1 \n");k=1;
38                 break;
39             }
40             else if(c[j]=='-')
41             {
42                     //cout<<"c["<<j<<"]=='-'"<<endl;
43                 if(c[j+1]=='0')
44                 {
45                     printf("1 \n");k=1;
46                     break;
47                 }
48             }
49             else if(l>sum||sum>r)
50             {
51                     //cout<<l<<" "<<sum<<" "<<r;
52                     printf("2 \n");k=1;
53                     break;
54             }
55 //            else if(flag==true)
56 //            {
57 //                if(l>(0-sum)||(0-sum)>r)
58 //                {
59 //                    printf("2 \n");k=1;
60 //                    break;
61 //                }
62 //            }
63         }
64         if(k==0) printf("0 \n");
65     }
66     return 0;
67 }

  草草一写,只得了5分,令小编十分伤心,于是小编就开始找自己写的漏洞,发现当l=-100,r=100时,输入100会输出1,这是为什么呢?还有输入0102时应该输出1,而这个程序却输出了2,小编才发现有些地方顺序不对,还有的多加了回车。于是更改如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 char c[1000000000];long long T,l,r,cnt,sum,k;bool flag;char x;
 5 int main()
 6 {
 7     scanf("%lld%lld%lld",&l,&r,&T);
 8     x=getchar();
 9     for(int i=1;i<=T;i++)
10     {
11         //x=getchar();
12         cnt=0;sum=0;flag=false;k=0;
13         for(;;)
14         {
15             c[++cnt]=getchar();//cout<<"1:"<<cnt<<" "<<c[cnt]<<endl;
16             //cout<<c[cnt]<<" "<<sum<<endl;
17             if(c[cnt]=='-') sum=0-sum;
18             else if(c[cnt]=='\n') break;
19             else
20             {
21                 sum*=10;sum+=(c[cnt]-48);
22             }
23
24         }
25 //        for(int j=1;j<=cnt;j++)
26 //        cout<<c[j];
27 //        cout<<endl;
28         //cout<<"1:"<<cnt<<" "<<sum<<endl;
29         for(int j=1;j<=cnt;j++)
30         {
31
32             //cout<<c[j]<<" "<<c[j+1]<<endl;
33              if(c[j]=='0'&&c[j+1]!='\n'&&j==1)
34             {
35                 //cout<<"c["<<j<<"]=='0'&&"<<cnt<<">2"<<endl;
36                 printf("1 \n");k=1;
37                 break;
38             }
39             else if((c[j]=='-'&&c[j+1]=='\n')||(c[j]=='-'&&c[j+1]=='0'))
40             {
41                     //cout<<"c["<<j<<"]=='-'"<<endl;
42                     printf("1 \n");k=1;
43                     break;
44             }
45             else if(l>sum||sum>r)
46             {
47                     //cout<<l<<" "<<sum<<" "<<r;
48                     printf("2 \n");k=1;
49                     break;
50             }
51 //            else if(flag==true)
52 //            {
53 //                if(l>(0-sum)||(0-sum)>r)
54 //                {
55 //                    printf("2 \n");k=1;
56 //                    break;
57 //                }
58 //            }
59         }
60         if(k==0) printf("0 \n");
61     }
62     return 0;
63 }

  一个可爱的10分,没事,不自卑,好歹多了5分,5分也是分啊。

那么究竟什么样的数不符合规则呢?

  • -0当然不符合,谁家0写‘-’号呢?
  • -当然也不合适,后面没有数字了。
  • 0……有前导0的当然也不行。
  • 爆long long的当然不可能正常。
  • 超过l,r范围的也不行。

  既然这些都不行,那么剩下的都可以喽,看了题解之后才发现缺了第4条的判断。思路很简单:先判断格式是否正确和是否爆unsigned long long,然后判断是否超出范围,总之一大堆判断模拟即可,代码如下:

 1 #include<iostream>
 2 #include<sstream>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 long long l,r,T,cnt=0,len=0;char c[100000];
 7 int main()
 8 {
 9     cin>>l>>r>>T;
10     for(int i=1;i<=T;i++)
11     {
12         len=0;cnt=0;
13         cin>>(c+1);//输入字符串,这么写是为了去掉多出的回车
14         len=strlen(c+1);
15         //cout<<c[1]<<endl;
16         if(c[1]=='-'&&(len==1||c[2]=='0'))//只有一个‘-’的和‘-0’当然不行
17         {
18             cout<<"1"<<endl;
19             continue;
20         }
21         else if(c[1]=='0'&&len!=1)//有前导0的也不行
22         {
23             cout<<"1"<<endl;
24             continue;
25         }
26         else if(c[1]=='-'&&len>20)//负数太小了不可能
27         {
28             cout<<"2"<<endl;
29             continue;
30         }
31         else if(c[1]!='-'&&len>19)//正数太大了不可能
32         {
33             cout<<"2"<<endl;
34             continue;
35         }
36         unsigned long long sum;//之前的处理是为了防止数字爆unsigned long long
37         long long x;//可以说x存的是sum的绝对值
38         if(c[1]=='-')
39         {
40             sscanf(c+2,"%llu",&sum);//注意在#include<cstdio>和#include<sstrea
41             if(sum>(1LL<<63))        //m>两个头文件下才可以使用,把字符串转换成
42             {                        //数字,当然,也可以手写。
43                 cout<<"2"<<endl;    //1LL表示(long long)1,1<<63表示1*2^63
44                 continue;
45             }
46             x=0-sum;
47         }
48         else
49         {
50             sscanf(c+1,"%llu",&sum);
51             if(sum>=(1LL<<63))
52             {
53                 cout<<"2"<<endl;
54                 continue;
55             }
56             x=sum;
57         }
58         if(x>=l&&x<=r) cout<<"0"<<endl;
59         else cout<<"2"<<endl;//超出范围当然不行
60     }
61     return 0;
62 }

接着看第二题:

                P5239 回忆京都

题目背景

第十五届东方人气投票 音乐部门 106名

第四次国内不知道东方的人对东方原曲的投票调查 51名

回忆京都副歌我tm吹爆,东方文花帖我tm吹爆!

题目描述

输入输出格式

输入格式:

第一行输入一个q,表示有q次询问。

第二行开始,一共q行,每行两个数字n,m,意思如题所示。

输出格式:

一共q行,对于每一个询问,都输出一个答案。

输入输出样例

输入样例#1: 复制

5
2 3
1 4
4 3
2 5
3 5

输出样例#1: 复制

10
10
11
35
50

  这道题一看就明白了,只要暴力求解不就行了吗,但是小编表示看不懂这个是干什么的,看了题解才发现这个式子是让求1~n和1~m的所有C的和,什么意思呢?举个例子。

  就比如说样例吧当m=2,n=3时,i的取值是1~2,j的取值是1~3,那么C₃¹+C₃²+C₃³+C₂¹+C₂²+C₁¹就是这一串式子的值。

  看完题解发现这道题是一道前缀和的模板题,之前学动态规划和树状数组的时候有点印象,那么什么是前缀和呢?好说,如图所示:

  像这样,有一个数组,里面有若干个数字,你的任务是输出每次询问的前i个数的和,但是这和我们的题有什么关系呢?别着急把它扩展成二维前缀和。

  如果每一个方格中存储的值都为C[i][j]的值,sum数组存的是前i行前j列所有C的和,那么就能得到动态规划的状态转移方程:

  sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+C[i][j]。

  这个状态转移方程应该比较好理解吧。举个例子,假设要求i=3,j=4时的sum值,那么sum[i][j]用方格可以表示为:

  sum[i-1][j]可以表示为:

  sum[i][j-1]可以表示为:

很显然,下图的棕色区域被算了2次,要减掉,同时加上C[i][j](深蓝色格子)的值,还要记得过程中不停取模。

  但是暴力去算每一个C都非常麻烦,不妨用动态规划的思路来解题,这种组合题对于每一个数,只有两种情况,要么选(共有C[i-1][j-1]种情况),要么不选(共有C[i][j-1]种情况),所以C[i][j]只和C[i-1][j-1],C[i][j-1]有关,得到以下状态转移方程:

  C[i][j]=C[i-1][j-1]+C[i][j-1]

  就这样按顺序递推,代码就出来了:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 long long c[1001][1001],sum[1001][1001],n,m,q;
 5 int main()
 6 {
 7     c[1][1]=1;c[1][0]=1;
 8     for(int i=2;i<=1000;i++)//打表
 9     {
10         c[i][0]=1;
11         for(int j=1;j<=i;j++)
12         c[i][j]=(c[i-1][j-1]+c[i-1][j])%19260817;
13     }
14     for(int i=1;i<=1000;i++)//打表
15     for(int j=1;j<=1000;j++)
16     sum[i][j]=(sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+c[i][j]+19260817)%19260817;
17     cin>>q;
18     for(int i=1;i<=q;i++)
19     {
20         cin>>m>>n;
21         cout<<sum[n][m]<<endl;//询问时直接输出即可
22     }
23     return 0;
24 } 

  为什么这道题可以打表呢?很简单,这道题的数据范围如下:

  n和m最大值只有1000,就不必一次一次慢慢算了,这样比较快。

   第三题和第四题居心叵测,坑害无数人,全网仅有1人AC,小编表示微积分离我太遥远,推荐大家看三题正解,四题正解。

转载于:https://www.cnblogs.com/TFLS-gzr/p/10464574.html

【洛谷月赛】洛谷三月月赛题解报告相关推荐

  1. 洛谷P5520 [yLOI2019] 青原樱 题解

    洛谷P5520 [yLOI2019] 青原樱 题解 题目链接:P5520 [yLOI2019] 青原樱 题意: n n n 个空放 m m m 个物品,两两物品不能直接相邻,至少空一格 纯数学题. 看 ...

  2. 洛谷P5633 最小度限制生成树 题解

    洛谷P5633 最小度限制生成树 题解 题目链接:P5633 最小度限制生成树 题意: 给你一个有 n n n 个节点, m m m 条边的带权无向图,你需要求得一个生成树,使边权总和最小,且满足编号 ...

  3. 洛谷P2619 [国家集训队]Tree I 题解

    洛谷P2619 [国家集训队]Tree I 题解 题目链接:P2619 [国家集训队]Tree I 题意: 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有 need\text{n ...

  4. 洛谷P1282 多米诺骨牌 题解

    洛谷P1282 多米诺骨牌 题解 题目链接:P1282 多米诺骨牌 题意: 多米诺骨牌由上下 222 个方块组成,每个方块中有 1∼61\sim61∼6 个点.现有排成行的上方块中点数之和记为 S1S ...

  5. 洛谷P4084 [USACO17DEC]Barn Painting G 题解

    洛谷P4084 [USACO17DEC]Barn Painting G 题解 题目链接:P4084 [USACO17DEC]Barn Painting G 题意:题意:给定一颗N个节点组成的树,3种颜 ...

  6. 洛谷P3237 [HNOI2014]米特运输 题解

    洛谷P3237 [HNOI2014]米特运输 题解 题目链接:P3237 [HNOI2014]米特运输 题意: 这题面是真的长啊 qwq 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为 ...

  7. 洛谷P4315 月下“毛景树” 题解

    洛谷P4315 月下"毛景树" 题解 题目链接:P4315 月下"毛景树" 题意:请维护一个数据结构,支持 改第 kkk 条边的边权 结点 uuu 到 vvv ...

  8. 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)

    洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...

  9. 洛谷P4287 [SHOI2011]双倍回文 题解

    洛谷P4287 [SHOI2011]双倍回文 题解 题目链接:P4287 [SHOI2011]双倍回文 题意: 记字符串 www 的倒置为 wRw^RwR .例如 (abcd)R=dcba(\tt{a ...

最新文章

  1. axure中怎么把图片变圆_orcad中怎么创建带图片的Title Block?
  2. hdu4539 郑厂长系列故事——排兵布阵 + POJ1158 炮兵阵地
  3. 数字电路技术基础一二章
  4. java小编程----括号是否匹配
  5. Vue - 去除控制台“你正在开发模式下运行Vue”的警告
  6. linux 2.6 添加系统调用,在Fedora 13里编译内核(linux-2.6.36)+添加系统调用
  7. 23.3. DELETE
  8. SSL自签署证书生成脚本
  9. 联想小新触摸板驱动_联想笔记本触摸板驱动下载
  10. 信道检测手机软件 ios_wifi分析仪如何检测周围wifi信号 wifi分析仪使用方法【详解】...
  11. roc_curve()的用法及用途
  12. 洛阳九县八取名字_洛阳市地图(洛阳市九县六区地图)
  13. 记录一次时间戳、夏令时、时区线上问题分析
  14. 闲鱼SPU体系构建的背后
  15. 社会神经网络有哪些,神经网络的神经网络
  16. Go语言中的字符串特性
  17. 你问我答:小匠,如何像你一样,做一个订阅号挣它 100 W?
  18. Android学习之下拉列表
  19. C语言snprintf函数
  20. 01Java并发编程的艺术之并发编程的挑战

热门文章

  1. Laradock 安装配置
  2. 软件测试工程师发展方向,主要有哪些?
  3. 国家网络信息安全第一章
  4. 上海财经应用统计考python_19上海财经大学应用统计专硕考研初试复试帖
  5. 4.4.1 ICMP报文的种类
  6. 八荣八耻(超强暴笑豪华版)
  7. audio: /dev/dsp: No such file or directory madplay
  8. remote_message
  9. 干谷净重694.27公斤 滦南国稻种芯-517功能性苦瓜稻北方旱作
  10. 基于稳定隶属度的自调优多峰聚类算法(SMMP)(SMMP)(Matlab代码实现)