Loading

【真题研究】CSP-S2020

[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;
}

[CSP-S2020] 动物园

很狗屎的题。

\(m\) 个饲料约束条件。如果有条件但是现有的动物没有一个满足的,说明此条件对应的饲料买不到了,因此新加的动物中不能有动物需要这款饲料。

翻译过来就是将 \(a_i\) 全部或运算起来,得到的二进制数。如果条件中 \(q_i\) 的位置为 \(0\),则累计贡献 \(Ans\) 一次。最后满足条件的动物数量便为 \(2^{k-Ans}\)。新增的动物数量为 \(2^{k-Ans}-n\)

时间复杂度 \(O(n+m)\),最后一个点会爆 long long,记得开 __int128

#include<bits/stdc++.h>
#define int __int128
#define rint register int
#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;

inline int read() {
  rint 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;
}

inline void print(int x) {
  if(x > 9) {
    print(x/10);
    putchar(x%10+'0');
  } else {
    putchar(x+'0');
  }
}

const int N = 1e6 + 10;

int n, m, c, k, a[N], Ans;

bitset<64> ans;

bool vis[65];

signed main() {
  n = read(), m = read(), c = read(), k = read();
  For(i,1,n) {
    a[i] = read();
    bitset<64> pos(a[i]);
    ans |= pos;
  }
  For(i,1,m) {
    int p = read(), q = read();
    if(ans[p] == 0 && !vis[p]) Ans++, vis[p] = 1;
  }
  print(((__int128)1 << (k - Ans)) - n);
  return 0;
}
posted @ 2024-10-24 11:01  Daniel_yzy  阅读(5)  评论(0编辑  收藏  举报