首页 > 其他分享 >Luogu P8651 题解

Luogu P8651 题解

时间:2023-10-05 15:46:28浏览次数:42  
标签:-% 02d 20 19 int P8651 break Luogu 题解

这是让我最崩溃的一道橙题了。

整整 11 次提交才 AC。

这道题有几个要点必须注意:

  • 判断日期是否合理。

  • 按顺序输出。

  • 判断重复的日期。


首先,我们来看怎么判断日期是否合理。

我们知道大月有 \(31\) 天,小月有 \(30\) 天,二月看平年闰年。

所以,我们可以写出这样的代码:

bool check(int y,int m,int d){
    if(d<=0)return 0;//特判
    if(m==1||m==3||m==5||m==7||m==8||m==10||m==12){//大月
        if(d<=31)return 1;
    }
    if(m==4||m==6||m==9||m==11){//小月
        if(d<=30)return 1;
    }
    if(m==2){//二月
        if(y%4==0){//闰年
            if(d<=29)return 1;
        }else{//平年
            if(d<=28)return 1;
        }
    }
    return 0;
}

接下来,我们需要按顺序输出日期。

我们发现,只有 \(A\) 和 \(C\) 会做年份,此时只要判断 \(A\) 和 \(C\) 哪一年更早即可。

接下来,如果年份相同,那么看月,所以比较 \(A\) 和 \(B\) 哪个更早。

我的输出是放在函数 void out(int n); 里面的,其中 \(n\) 为 \(1,2,3\) 中的一数,表示三种格式。

注意判断年份是 \(19\) 开头还是 \(20\) 开头,并且日期和月份不足两位要输出前导零。

void out(int n){//输出
    switch(n){
        case 1:{//年月日
            if(check(a,b,c)){
                printf("%d%02d-%02d-%02d\n",a>=60?19:20,a,b,c);
            }
            break;// break 很重要
        }
        case 2:{//月日年
            if(check(c,a,b)){
                printf("%d%02d-%02d-%02d\n",c>=60?19:20,c,a,b);
            }
            break;
        }
        case 3:{//日月年
            if(check(c,b,a)){
                printf("%d%02d-%02d-%02d\n",c>=60?19:20,c,b,a);
            }
            break;
        }
    }
}
signed main(){
    scanf("%d/%d/%d",&a,&b,&c);//输入
    if(a<60)a+=100;
    if(c<60)c+=100;//年份小于 60 要加上 100
    if(a<c){//年份比较大小
        a%=100;
        c%=100;//变回原来的样子
        out(1);
        if(a<b){
            if(c!=a||a!=b||b!=c){//判断重复!!!
                out(2);
                if(b!=a)out(3);
            }
        }else{
            if(c!=a){
                out(3);
                if(b!=a)out(2);
            }
            
        }
    }else{//下面和上面一个道理
        a%=100;
        c%=100;
        if(a<b){
            if(c!=a||a!=b||b!=c){
                out(2);
                if(b!=a)out(3);
            }
        }else{
            if(c!=a){
                out(3);
                if(b!=a)out(2);
            }
        }
        out(1);
    }
    return 0;
}

还有一点也很重要,记得判断重复的日期。

比如输入为 01/01/00 时,你的代码很可能输出两个 2000-01-01,这样会 WA。

判重请看上面的代码理解一下。


AC Code:

#include<iostream>
using namespace std;
int a,b,c;
bool check(int y,int m,int d){
    if(d<=0)return 0;//特判
    if(m==1||m==3||m==5||m==7||m==8||m==10||m==12){//大月
        if(d<=31)return 1;
    }
    if(m==4||m==6||m==9||m==11){//小月
        if(d<=30)return 1;
    }
    if(m==2){//二月
        if(y%4==0){//闰年
            if(d<=29)return 1;
        }else{//平年
            if(d<=28)return 1;
        }
    }
    return 0;
}
void out(int n){//输出
    switch(n){
        case 1:{//年月日
            if(check(a,b,c)){
                printf("%d%02d-%02d-%02d\n",a>=60?19:20,a,b,c);
            }
            break;// break 很重要
        }
        case 2:{//月日年
            if(check(c,a,b)){
                printf("%d%02d-%02d-%02d\n",c>=60?19:20,c,a,b);
            }
            break;
        }
        case 3:{//日月年
            if(check(c,b,a)){
                printf("%d%02d-%02d-%02d\n",c>=60?19:20,c,b,a);
            }
            break;
        }
    }
}
signed main(){
    scanf("%d/%d/%d",&a,&b,&c);//输入
    if(a<60)a+=100;
    if(c<60)c+=100;//年份小于 60 要加上 100
    if(a<c){//年份比较大小
        a%=100;
        c%=100;//变回原来的样子
        out(1);
        if(a<b){
            if(c!=a||a!=b||b!=c){//判断重复!!!
                out(2);
                if(b!=a)out(3);
            }
        }else{
            if(c!=a){
                out(3);
                if(b!=a)out(2);
            }
            
        }
    }else{//下面和上面一个道理
        a%=100;
        c%=100;
        if(a<b){
            if(c!=a||a!=b||b!=c){
                out(2);
                if(b!=a)out(3);
            }
        }else{
            if(c!=a){
                out(3);
                if(b!=a)out(2);
            }
        }
        out(1);
    }
    return 0;
}

标签:-%,02d,20,19,int,P8651,break,Luogu,题解
From: https://www.cnblogs.com/I-like-magic/p/Luogu-P8651.html

相关文章

  • Luogu CF1469B 题解
    这道题其实并不难。题目大意是这样的:已知两个序列\(r\)和\(b\),求出合并后的最大前缀和。很好发现:答案就是\(r\)和\(b\)各自的最大前缀和之和。但要注意:\(r\)和\(b\)可以什么都不取,因此\(maxa\)和\(maxb\)初始要赋值为\(0\)。ACCode:#include<iostream>using......
  • Luogu CF755B 题解
    这题其实不难。两人最佳的方案就是先说对方会的词。不难证明,设先手会说\(n\)个单词,后手会说\(m\)个单词,若\(n>m\),则先手胜,若\(n<m\),则后手胜。那如果\(n=m\)呢?假设两人都会说的单词数为\(k\),那么一番推理发现,当两人说了\(k-1\)次,就没有两人都会的词了,可以回到之......
  • Luogu CF1133B 题解
    这道题其实很简单要让两数和为\(k\)的倍数,需要满足以下两条件之一:两数都是\(k\)的倍数两数的余数和为\(k\)因此,我们可以先统计出余数再按上述条件算出共有多少组,即可得到答案注意:当\(k\)为偶数时,余数为\(k/2\)的数要两两配对,不要多算这里统计的是组数,......
  • Luogu P7627 题解
    这题其实不难但如果用暴力,肯定过不了所以我们得想另一种办法我们发现,只有\(1\)异或\(0\)的值为\(1\)例如:\(1\),\(0\),\(1\)两两异或的和为2其实就是每个\(0\)与每一个\(1\)异或时,\(sum\)要加\(1\)所以,我们只要把每一位的\(0\)和\(1\)的数量都统计出来......
  • Luogu CF400C 题解
    这道题其实不难,只是一道非常简单的模拟题。我们发现,每顺时针转动\(4\)次、镜面对称\(2\)次、逆时针旋转\(4\)次,就变回原来的样子了。所以,在操作前,我们可以让\(x\getsx\bmod4\),\(y\getsy\bmod2\),\(z\getsz\bmod4\)。接下来,只需在草稿纸上画一画,即可知道顺时针转一次,一......
  • CodeForces 814E An unavoidable detour for home 题解
    更好的阅读体验题意题目链接(洛谷翻译)给出\(n\)个点,和每个点的度\(d_i\)让你构造出一张无向图满足以下两条性质:点\(1\)到点\(i\)仅有唯一一条最短路。点\(1\)到点\(i\)的最短路长度大于等于点\(1\)到点\(i-1\)的最短路长度。求能构成满足条件的无向图......
  • Luogu 300 粉粉福
    由于第二张图片是分期制作的,所以两次爬头像时,粉丝列表顺序可能会有微小的变动(比如取关会让后面的人往前一位),这就导致了有极少数粉丝被漏掉了。在此,我对大家道歉所有粉丝头像第一张图是动图,第二张图是一个\(1600\times1800\)的图片第一张图片加载可能比较慢封禁用户不在图片......
  • [题解] CF474E Pillars
    题意给定长度为\(n\)的序列\(a\)和常数\(d\),输出一个最长的\(a\)的子序列,使得相邻两项的差的绝对值大于等于\(d\)。\(n\le10^5\)题解数据结构优化DP的板子题了吧。首先,这道题看上去就很LIS,我们尝试着用类似LIS的思路去做。设\(f_i\)表示以\(i\)结尾的符合......
  • 题解 accoders::NOI 5510【飞翔的胖鸟(fly)】
    题解accoders::NOI5510【飞翔的胖鸟(fly)】problem求\(f(x)=\frac{ah}{\sin(x)}+bx\)在\((0,\frac\pi2]\)上的最小值。solution\(\sin'(x)=cos(x);\cos'(x)=-\sin(x)\)。\((f(x)\cdotg(x))'=f'(x)g(x)+f(x)g'(x)\)。\(\left(\dfrac{f......
  • 题解 accoders::NOI 5508【漂亮大厨(cook)】
    题解accoders::NOI5508【漂亮大厨(cook)】part1区间加\(x\),区间询问有多少个数字\(\leqy\)。\(n,m\leq10^5,x\leq200,y\leq10^7\)。考虑P5356[Ynoi2017]由乃打扑克的做法,分块,块内按照值排序。修改就整块打tag,散块暴力重构(可以归并排序重构);询问在整块上二分,散块暴力......