【GDOI2022PJD2T3 教室的电子钟】题解

D2T3 教室的电子钟

题目

为了迎接 GDOI,小蒟蒻学校所有教室的钟都换成了电子钟。电子钟会显示年月日时分秒的信息,每天的时间从 00:00:00 到 23:59:59。电子钟共有 14 个格子,共 14 × 7 = 98 个 LED 灯管组成。

image

具体来说,每个格子都是下面的十种状态中的一种,可以看到每个数字都是有 7 个 LED 灯管的亮暗状态呈现的:

image

这个钟的设计非常奇怪,每个灯管保持亮和保持暗的时候都是不消耗电的,每当由暗变成亮或者由亮变成暗则要消耗 1 个单位的电。小蒟蒻想知道,在需要考虑平闰年的真实情况下,从 \(X\)\(Y\)\(Z\)\(A\)\(B\)\(C\) 秒起,到 \(X′\)\(Y ′\)\(Z′\) 日到 \(A′\)\(B′\)\(C′\) 秒一共消耗了多少单位的电。

为了解决这道题,小蒟蒻想向你介绍一些他在科学课上学到的知识。

对于平年来说,每个月对应的天数如下:

image

对于闰年来说,每个月对应的天数如下:

image

其中闰年指的是年份能被 4 整除且不能被 100 整除,或者能被 400 整除的年份。平年则是不是闰年的年份。例如 2020 年是闰年,1900 年不是闰年。

image

思路

对于前70分,暴力模拟即可。

我们先弄出一个 \(10 \times 10\) 的表格,分别代表每个数字变成另一个数字所需要的代价,然后一秒一秒跳。

对于后30分,我们可以把年和后面的分开。先预处理平年和闰年情况变为常量,然后每一年分类讨论即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'
){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x
<<3)+(ch^48);ch=getchar();}return x*f;}
//#define N
//#define M
//#define mo
int n, m, i, j, k, T;
int mp[10]={6, 2, 5, 5, 4, 5, 6, 3, 7, 6}; 
int b[10][10]=
{
  0, 4, 3, 3, 4, 3, 2, 3, 1, 2, 
  4, 0, 5, 3, 2, 5, 6, 1, 5, 4, 
  3, 5, 0, 2, 5, 4, 3, 4, 2, 3, 
  3, 3, 2, 0, 3, 2, 3, 2, 2, 1, 
  4, 2, 5, 3, 0, 3, 4, 3, 3, 2, 
  3, 5, 4, 2, 3, 0, 1, 4, 2, 1, 
  2, 6, 3, 3, 4, 1, 0, 5, 1, 2, 
  3, 1, 4, 2, 3, 4, 5, 0, 4, 3, 
  1, 5, 2, 2, 3, 2, 1, 4, 0, 1, 
  2, 4, 3, 1, 2, 1, 2, 3, 1, 0
}; 
int mth[15]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0, 0}; 
int n1, yu1, r1, s1, f1, m1; 
int n2, yu2, r2, s2, f2, m2; 
int ans=0; 
const int ping_nian=106904682; 
const int run_nian=107197568;  
 
void bian(int x, int y, int z)
{
    int sum=0; 
//  printf("%lld->%lld: ", x, y); 
    while(z--) sum+=b[x%10][y%10], x/=10, y/=10; 
//  printf("%lld\n", sum); 
    ans+=sum; 
}
 
int pan(int x)
{
    if(x%400==0) return 1; 
    if(x%100==0) return 0; 
    if(x%4==0) return 1; 
    return 0; 
}
 
int cong()
{
    while(n1!=n2 || yu1!=yu2 || r1!=r2 || s1!=s2 || f1!=f2 || m1!=m2)  
    {
        if(m1<59) bian(m1, m1+1, 2), ++m1; 
        else
        {
            bian(m1, 0, 2); m1=0; 
            if(f1<59) bian(f1, f1+1, 2), ++f1; 
            else
            {
                bian(f1, 0, 2); f1=0; 
                if(s1<23) bian(s1, s1+1, 2), ++s1; 
                else
                {
                    bian(s1, 0, 2); s1=0; 
                    if(r1<(yu1==2 ? (pan(n1) ? 29 : 28) : mth[yu1])) bian(r1, r1+1, 2), ++r1; 
                    else
                    {
                        bian(r1, 1, 2); r1=1; 
                        if(yu1<12) bian(yu1, yu1+1, 2), ++yu1; 
                        else
                        {
                            bian(yu1, 1, 2); yu1=1; 
                            bian(n1, n1+1, 4); ++n1;  
                        }
                    }
                }
            }
        }
    }
    return ans; 
}
 
void zhuan() 
{
	while(n1+1<n2)
	{
		if(pan(n1)) 
		{
			if(yu1<2) ans+=run_nian; 
			else if(yu1==2 && r1<29) ans+=run_nian; 
			else ans+=ping_nian; 
		}
		else if(pan(n1+1))
		{
			if(yu1<2) ans+=ping_nian; 
			else if(yu1==2 && r1<29) ans+=ping_nian; 
			else ans+=run_nian; 
		}
		else ans+=ping_nian; 
		bian(n1, n1+1, 4), ++n1; 
	}
}
 
signed main()
{
	// 107197568
//	printf("%lld\n", qiu());
    scanf("%lld%lld%lld%lld%lld%lld", &n1, &yu1, &r1, &s1, &f1, &m1); 
    scanf("%lld%lld%lld%lld%lld%lld", &n2, &yu2, &r2, &s2, &f2, &m2); 
	zhuan(); 
    printf("%lld", cong()); 
//	printf("%lld", qiu()); 
    return 0;
}

总结

细节处理题。

对于做日历类的数据处理题的时候,有几点需要注意:

  • 平年闰年在什么时候
  • 2月前和2月后该算成哪一年

对于电子钟类题目,要注意是求的是变化还是亮的个数。

posted @ 2022-04-25 17:49  zhangtingxi  阅读(68)  评论(0编辑  收藏  举报