首页 > 其他分享 >【真题研究】CSP-S2020

【真题研究】CSP-S2020

时间:2024-10-24 11:01:40浏览次数:1  
标签:真题 int 31 else S2020 dY 366 365 CSP

[CSP-S2020] 儒略日

大模拟。

可以将时间分为 \(4\) 个部分:

  1. \(-4713.1.1\) 至 \(-1.12.31\)
  2. \(1.1.1\) 至 \(1582.10.4\)
  3. \(1582.10.5\) 至 \(1582.10.14\)
  4. \(1582.10.15\) 至无穷

大体可分为公元前(儒略历),公元后儒略历,公元后格里高利历。

如果 \(x\le 1721424\),说明是公元前儒略历,\(4\) 年一打包,其中 \(1\) 个闰年和 \(3\) 个平年,共 \(1461\) 天。然后按周期推年份。推完年份剩下的天数用来推月份,天数即可,注意判断闰年。

void bc(int x) {
  int dY = x / zq1, i, op = 0; x %= zq1;
  for (i = 0; i < 4; i++) {
    if(i % 4 == 0 && x > 366) x -= 366;
    else if(i % 4 != 0 && x > 365) x -= 365;
    else break;
  }
  Y = 4713 - (dY * 4 + i);
  if(x == 0) {
    D = 31, M = 12;
    Y++;
    return ;
  }
  if(i == 0) op = 1;
  for (i = 1; i <= 12; i++) {
    int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
    if(x > del) x -= del;
    else break;
  }
  M = i;
  D = x;
  return ;
}

如果 \(1721424 < x \le 2299161\),说明是公元后儒略历,和公元前儒略历类似,不过多赘述。

void BBC(int x) {
  int dY = x / zq1, i, op = 0; x %= zq1;
  for (i = 1; i <= 4; i++) {
    if(i % 4 == 0 && x > 366) x -= 366;
    else if(i % 4 != 0 && x > 365) x -= 365;
    else break;
  }
  Y = (dY * 4 + i);
  if(x == 0) {
    D = 31, M = 12;
    Y--;
    return ;
  }
  if(Y % 4 == 0) op = 1;
  for (i = 1; i <= 12; i++) {
    int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
    if(x > del) x -= del;
    else break;
  }
  M = i;
  D = x;
  return ;
}

然后是日期删除的部分,直接跳过\(1582.10.5\) 到 \(1582.10.15\) 日。然后进入到公元后格里高利历。由于 \(1582\) 年是从 \(10.15\) 开始的,所以要特判断掉这一年。到 \(1582.12.31\) 共 \(78\) 天。

if(x <= 78) {
  if(x <= 17) {
    M = 10, D = 15+x-1;
  } else if(x <= 47) {
    x -= 17;
    M = 11, D = x;
  } else {
    x -= 47;
    M = 12, D = x;
  }
  Y = 1582;
  cout << D << ' ' << M << ' ' << Y << '\n';
  return ;
}

然后按 \(400\) 年为一周期打包,一个周期有 \(97\) 个闰年和 \(303\) 个平年,共 \(97\times 366+303\times 365=146097\) 天。推完年份剩下的天数用来推月份,天数即可,注意判断闰年需要把 \(1582\) 年和包内的年份一起算上判断。

int dY = (x / y400), i, op = 0; x %= y400;
for (i = 1; i <= 400; i++) {
  if(check(1582 + dY * 400 + i) && x > 366) x -= 366;
  else if(!check(1582 + dY * 400 + i) && x > 365) x -= 365;
  else break;
}
Y = 1582 + dY * 400 + i;
if(x == 0) {
  M = 12, D = 31;
  Y--;
  goto ans2;
}
if(check(Y)) op = 1;
for (i = 1; i <= 12; i++) {
  int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
  if(x > del) x -= del;
  else break;
}
M = i;
D = x;
ans2: cout << D << ' ' << M << ' ' << Y << '\n';

然后整合起来,分类讨论即可。

时间复杂度 \(O(q)\)。

#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)

using namespace std;

const int Mth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

const int zq1 = 1461, BC = 1721424, k1582 = 577737, y400 = 146097;

int q, x, D, M, Y;

bool check(int x) {
  if(x % 400 == 0) return 1;
  if(x % 4 == 0 && x % 100 != 0) return 1;
  return 0;
}

void BBC(int x) {
  int dY = x / zq1, i, op = 0; x %= zq1;
  for (i = 1; i <= 4; i++) {
    if(i % 4 == 0 && x > 366) x -= 366;
    else if(i % 4 != 0 && x > 365) x -= 365;
    else break;
  }
  Y = (dY * 4 + i);
  if(x == 0) {
    D = 31, M = 12;
    Y--;
    return ;
  }
  if(Y % 4 == 0) op = 1;
  for (i = 1; i <= 12; i++) {
    int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
    if(x > del) x -= del;
    else break;
  }
  M = i;
  D = x;
  return ;
}

void bc(int x) {
  int dY = x / zq1, i, op = 0; x %= zq1;
  for (i = 0; i < 4; i++) {
    if(i % 4 == 0 && x > 366) x -= 366;
    else if(i % 4 != 0 && x > 365) x -= 365;
    else break;
  }
  Y = 4713 - (dY * 4 + i);
  if(x == 0) {
    D = 31, M = 12;
    Y++;
    return ;
  }
  if(i == 0) op = 1;
  for (i = 1; i <= 12; i++) {
    int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
    if(x > del) x -= del;
    else break;
  }
  M = i;
  D = x;
  return ;
}

void solve() {
  D = M = Y = 0;
  cin >> x; x++;
  if(x <= BC) {
    bc(x);
    cout << D << ' ' << M << ' ' << Y << " BC\n";
  } else {
    x -= BC;
    if(x <= k1582) {
      BBC(x);
      cout << D << ' ' << M << ' ' << Y << '\n';
    } else {
      x -= k1582;
      if(x <= 78) {
        if(x <= 17) {
          M = 10, D = 15+x-1;
        } else if(x <= 47) {
          x -= 17;
          M = 11, D = x;
        } else {
          x -= 47;
          M = 12, D = x;
        }
        Y = 1582;
        cout << D << ' ' << M << ' ' << Y << '\n';
        return ;
      }
      x -= 78;
      int dY = (x / y400), i, op = 0; x %= y400;
      for (i = 1; i <= 400; i++) {
        if(check(1582 + dY * 400 + i) && x > 366) x -= 366;
        else if(!check(1582 + dY * 400 + i) && x > 365) x -= 365;
        else break;
      }
      Y = 1582 + dY * 400 + i;
      if(x == 0) {
        M = 12, D = 31;
        Y--;
        goto ans2;
      }
      if(check(Y)) op = 1;
      for (i = 1; i <= 12; i++) {
        int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
        if(x > del) x -= del;
        else break;
      }
      M = i;
      D = x;
      ans2: cout << D << ' ' << M << ' ' << Y << '\n';
    }
  }
}

signed main() {
  ios::sync_with_stdio(0);
  cin.tie(nullptr), cout.tie(nullptr);
  cin >> q;
  while(q--) solve();
  return 0;
}

标签:真题,int,31,else,S2020,dY,366,365,CSP
From: https://www.cnblogs.com/Daniel-yao/p/18499136

相关文章

  • 2024.10.23总结+CSP2024前总结
    赛时T1看完一脸懵逼啊,画了好几个立方体,一直觉得切四刀是14块,然后也找不到什么规律,就去看后面的题了,jsy说是15之后还是没想法,只觉着\(7=2^3-1\),\(15=2^4-1\),当\(n<=m\)时是\(2^n\),后来看回来把已知情况全列出来,找到\(f[i][j]=f[i][j-1]+f[i-1][j-1]\)的递推式,写了60pts的,但WA了......
  • 【真题研究】CSP-S2019
    [CSP-S2019]格雷码很简单的规律题。考虑决策每一位的\(0/1\),从高位往低位决策。将\(k\)可以看作当前的排名。第\(i\)位若\(2^{i-1}<k\),说明当前位为\(0\)。否则当前位为\(1\),并将排名更新为\(k=2^i-k-1\)然后继续决策即可。时间复杂度\(O(n)\),递归或循环实现都可......
  • CSP-S 2024 第二轮认证——游记
    CSP游记Day-3学校办运动会了,机房有勇夫参赛,第一轮OUT。FRZ_29大佬直接开卷,蹲守机房,泡面为伴,结果被无可奈何花落去搞得一天无可奈何。本蒟蒻play了一个上午,下午回到机房,发现FRZ_29大佬已经卷了一个上午,直接当场%%%%%。晚饭也是吃机房特产,精品美食泡面(bushi)。晚上尝试驯服Li......
  • P7074 [CSP-J2020] 方格取数 题解
    动态规划dp方格取数类似于数字三角形,均可以使用动态规划直接秒杀.但此题有$3$个方向:上、右、下.所以可以定义一个三维数组dp数组.假设$f_{i,j,1}$是从右、上方到达$(i,j)$的和的最大值.又有$f_{i,j,0}$是从右、下方到达$(i,j)$的和的最大值.我们可以先确定......
  • P7912 [CSP-J 2021] 小熊的果篮 题解
    是模拟吗?其实是的,虽然$1\len\le2\times10^5$,但是队列是个好东西.我们定义一个结构体,来存放每一个块的信息,包括类型、起点、终点,将它们放入队列当中,再使用基于广搜的思想,先处理,再合并,所以需要用到$2$个队列.注意点数据中可能会有块的类型全是$1$,或者全是$0$的情况......
  • P7071 [CSP-J2020] 优秀的拆分 题解
    二进制"优秀的拆分"如果存在,则代表$n$的二进制最低位不是$1$.$\because2^0=1$$\therefore$当$n$的二进制最低位为$1$时,不存在优秀的拆分.即$n$不是奇数.上述条件判断完后,就可以从$2$的$30$次方开始模拟(int的上限是$2^{31}-1$).代码#include<iostream>......
  • P7072 [CSP-J2020] 直播获奖 题解
    暴力使用$\Theta(n^2)$的时间复杂度来解决这题大约能拿到$60pts$.即枚举$p$,再枚举每个选手的分数.正解桶是个好东西.我们开一个桶,记录当前分数有多少人.然后计算获奖人数,分数从大到小进行枚举,直到当前人数$\ge$获奖人数.代码#include<iostream>#include<cstdio>#i......
  • [CSP-J2020] 表达式 题解
    短路这道题目中所含的运算符只有3个:与、或、非.在与运算和或运算中有2个性质.进行与运算时,若其中有一个值为0,则这个运算的结果就为0,即无需判断另1个数是否是0或1.进行或运算时,若其中有一个值为1,则这个运算的结果就为1,也无需判断另一个数是否是0或1.表达式树根据短路的性......
  • CSP-J 2024 游记
    CSP-J2024游记Day\(-3\)忐忑不安地期待。做了一套模拟。ProblemScoreDifficultiesA\(100\)入门B\(50\)(贪心策略错了)普及-C\(50\)(双重循环\(n<=10^5\))普及D\(20\)(dp+前缀和,我写的DFS)普及+B题交完废了,幸好后面\(2\)题还行,总分......
  • CSP模拟赛 #43
    A一棵树,每次加入一条路径,或者查询一条给定路径包含的路径个数。\(n,m,q\le10^5\)矩形加法,单调查询,三维偏序,cdq分治。B一棵树,有\(n+1\)层,第\(i\)层有\(i\)个点。对于第\(i(1\lei\len)\)层,点的编号分别为\(\frac{i(i-1)}2+1\sim\frac{i(i+1)}2\),该层的第......