「CSP-S2020」题解

开个坑,边改边更,不然等我全部改完都不知道猴年马月了...

儒略日

令人心累的模拟,我想如果我当时没做这道题的话结果一定会更好一点吧...
下来之后听学长说了他的实现思路,也看了他的码(56行,算上头文件),感觉确实挺SB的,但现实就是这样,没写出来就是没写出来。也没什么好抱怨的吧,毕竟是自己做的选择,决策的错误根本上还是经验跟能力不足。与其抱怨还不如吸取教训,以及庆幸今年还有一次机会,多了一张复活券,就要把他的作用发挥到最好。

最后还是磕磕绊绊地把自己考场的代码完善了,没有换思路,连重构带调码花了大半个下午加小半个晚上(当然最后查出来是一个写错变量的sb错误的时候自闭了好半天),如果没有标程帮忙检验的话估计时间会更长,可能换学长的思路或者题解的思路的话的确会好写好调一点,毕竟有代码在那,但写完自己的码也算是给当初考场上SB的自己一个交代吧。

思路:

首先将时间按闰年的计算方式分成两种:1. 1582年10月4号及以前 2. 1582年10月15号及以后

  1. 这种情况很好做,直接初始年份设为-4713,然后按4年1461的循环节跳即可,跳完循环节在一年年跳,此时判断闰年的方式就是看mod4的余数是否为3(负数要先%4再+4再%4)。最后如果年份>=0了就把年份++。月份也是直接跳即可。

  2. 先把1582年10月份,11月份,12月份这样散的日子特判掉。然后再判一个1583到1599的,一年年直接暴力跳即可,要注意的是此时闰年的判定方式要改一下。再剩下就是1600年及以后的了,此时直接先跳400年的大循环节,跳完400年直接1年年跳就行,还是注意判断闰年,最多跳399次,数据组数1e5够用了。

需要注意的是跳循环节时我的日期都是默认从某年的1月1日开始的,跳一次就是跳到下一个循环开始年份的1月1号,这样在每个特判点一开始减去特判值的时候要多减一个1。

code: 又臭又长,不建议看,下面有学长的代码,但是当个标程算一下答案还是行的。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int flag = 2299160;
#define int long long
int year[4] = { 366, 365, 365, 365 };
int month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
ll n;
ll nian;
ll yue;
ll tian;
void Solve1() {
    nian = -4713;
    yue = 1;
    tian = 1;
    nian += 4 * (n / 1461);
    n %= 1461;
    for (int i = 0; i < 4; ++i) {
        if (n < year[i])
            break;
        nian++;
        n -= year[i];
    }
    int op = 0;
    if (((nian % 4) + 4) % 4 == 3)
        op = 1;
    for (int i = 0; i < 12; ++i) {
        int res = month[i];
        if (op && i == 1)
            res++;
        if (n < res)
            break;
        yue++;
        n -= res;
    }
    if (nian >= 0)
        nian++;
    tian += n;
    printf("%lld %lld %lld", tian, yue, abs(nian));
    if (nian < 0)
        printf(" BC\n");
    else
        printf("\n");
}
void Solve2() {
    n -= flag;
    if (n <= 17) {
        nian = 1582;
        yue = 10;
        tian = 14 + n;
    } else if (n <= 47) {
        nian = 1582;
        yue = 11;
        tian = n - 17;
    } else if (n <= 78) {
        nian = 1582;
        yue = 12;
        tian = n - 47;
    } else if (n <= 443) {
        nian = 1583;
        yue = 1;
        n -= 78;
        for (int i = 0; i < 12; ++i) {
            int res = month[i];
            if (n <= month[i])
                break;
            yue++;
            n -= res;
        }
        tian = n;
    } else if (n <= 6287) {
        n -= 444;
        nian = 1584;
        int res;
        if (nian % 400 == 0)
            res = 366;
        else {
            if (nian % 100 == 0)
                res = 365;
            else if (nian % 4 == 0)
                res = 366;
            else
                res = 365;
        }
        while (n >= res) {
            nian++;
            n -= res;
            if (nian % 400 == 0)
                res = 366;
            else {
                if (nian % 100 == 0)
                    res = 365;
                else if (nian % 4 == 0)
                    res = 366;
                else
                    res = 365;
            }
        }
        yue = 1;
        int op = 0;
        if (nian % 400 == 0)
            op = 1;
        else {
            if (nian % 100 == 0)
                op = 0;
            else if (nian % 4 == 0)
                op = 1;
            else
                op = 0;
        }
        for (register int i = 0; i < 12; ++i) {
            res = month[i];
            if (i == 1 && op)
                res++;
            if (n < res)
                break;
            n -= res;
            yue++;
        }
        tian = 1 + n;
    } else {
        n -= 6288;
        nian = 1600;
        nian += 400 * (n / 146097);
        n %= 146097;
        int res = 366;
        while (n >= res) {
            nian++;
            n -= res;
            if (nian % 400 == 0)
                res = 366;
            else {
                if (nian % 100 == 0)
                    res = 365;
                else if (nian % 4 == 0)
                    res = 366;
                else
                    res = 365;
            }
        }
        int op = 0;
        if (nian % 400 == 0)
            op = 1;
        else {
            if (nian % 100 == 0)
                op = 0;
            else if (nian % 4 == 0)
                op = 1;
            else
                op = 0;
        }
        yue = 1;
        for (register int i = 0; i < 12; ++i) {
            res = month[i];
            if (i == 1 && op)
                res++;
            if (n < res)
                break;
            n -= res;
            yue++;
        }
        tian = 1 + n;
    }
    printf("%lld %lld %lld\n", tian, yue, nian);
}
signed main() {
    freopen("julian.in", "r", stdin);
    freopen("julian.out", "w", stdout);
    int t;
    cin >> t;
    while (t--) {
        scanf("%lld", &n);
        if (n <= flag)
            Solve1();
        else
            Solve2();
    }
}

更优美的学长考场代码:

#include <bits/stdc++.h>

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

bool check(int x) {
	if (x < 1582) return x % 4 == 0;
	else return x % 400 == 0 || (x % 4 == 0 && x % 100);
}

int daynum(int y, int m) {
	if (m == 2) return 28 + check(y);
	else return num[m];
}

int main() {
	freopen("julian.in", "r", stdin);
	freopen("julian.out", "w", stdout);
	int q;
	std::cin >> q;
	while (q--) {
		int y, m;
		long long n, d;
		scanf("%lld", &n);
		if (n >= 2299161) {
			n -= 2299161, y = 1582, m = 10, d = 15 + n;
			while (d > 14609700000) d -= 14609700000, y += 40000000;
			while (d > 1460970000 ) d -= 1460970000 , y += 4000000;
			while (d > 146097000  ) d -= 146097000  , y += 400000;
			while (d > 14609700   ) d -= 14609700   , y += 40000;
			while (d > 1460970    ) d -= 1460970    , y += 4000;
			while (d > 146097     ) d -= 146097     , y += 400;
			if (d > 31) {
				d -= 31, ++m;
				if (d > 30) {
					d -= 30, ++m;
					if (d > 31) {
						d -= 31, m = 1, ++y;
					}
				}
			}
			while (d > 365 + check(y)) d -= 365 + check(y++);
			while (m < 12 && d > daynum(y, m)) d -= daynum(y, m++);
		}
		else {
			y = -4712, m = 1, d = 1 + n;
			while (d > 1461000) d -= 1461000, y += 4000;
			while (d > 146100 ) d -= 146100 , y += 400;
			while (d > 365 + check(y)) d -= 365 + check(y++);
			while (m < 12 && d > daynum(y, m)) d -= daynum(y, m++);
		}
		if (y <= 0) --y;
		printf("%lld %d %d", d, m, (int)std::abs(y));
		if (y <= 0) puts(" BC");
		else puts("");
	}
}

动物园

SB题,我没写出来,我是SB。

在保证\(q_i\)互不相同的情况下,\(c\)\(q_i\)除了影响你读入之外卵用没有。

显然直接考虑每一位就行,如果一个二进制位没被限制或者已经养的动物里这一位上有1,那么cnt+1。

维护养的动物的每一位的1的情况直接求或和即可,因为只要有一个是1就行。跟没被限制的位取并。

答案就是\(2^{cnt}-n\)

\(1ull<<64\)是未定义的,会出错,可以写成\((0ull-n)\)或者\(((1ull << 63) << 1) - n\)

注意这玩意最大连 unsigned long long 都能爆,此时只能用计算器手算然后特判输出。

#include <cstdio>
#include <iostream>
typedef unsigned long long ull;

int n, m, c, K, pos, cnt;
ull st, x;
bool hav[66];

int main() {
	//freopen("zoo.in", "r", stdin), freopen("zoo.out", "w", stdout);
	std:: cin >> n >> m >> c >> K;
	for (int i = 1; i <= n; ++i) scanf("%llu", &x), st |= x;
	for (int i = 1; i <= m; ++i) scanf("%d", &pos), hav[pos] = 1, scanf("%d", &pos);
	for (ull i = 0; i < K; ++i) cnt += ((st >> i) & 1) || !hav[i];
	if (!n && cnt == 64) puts("18446744073709551616");
	else if (cnt == 64) std:: cout << 0ull - n ;
	else std:: cout << (1ull << cnt) - n ;
	return 0;
}

函数调用

看大佬博客吧,我也是看的这篇:比我小但是能把我按在地上踩的大佬

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

namespace PiGeonZ {
    int s, w;
    char buf[1 << 20], *p1 = buf, *p2 = buf, c;
    #define gc() (p1 == p2 ? ((p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin)) == p1 ? EOF : *p1++) : *p1++)
    inline int read() {
        s = 0, w = 1, c = gc();
	while (c < '0' || c > '9') { if (c == '-') w = -1; c = gc(); }
	while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = gc();
	return s * w;
    }
}
using PiGeonZ:: read;

const int maxn = 1e5 + 10;
const int maxm = 1e6 + 10;
const int mod = 998244353;

int n, m, Q, mult;
int a[maxn], q[maxn], f[maxn], add[maxn], deg[maxn], tpy[maxn], pos[maxn], val[maxn], mul[maxn];
bool vis[maxn];
vector<int> e[maxn];
queue<int> que;

void dfs(int u) {
    vis[u] = 1;
    mul[u] = (tpy[u] == 2 ? val[u] : 1);
    for (int i = 0; i < (int) e[u].size(); ++i) {
        int v = e[u][i];
        if (!vis[v]) dfs(v);
        mul[u] = 1ll * mul[u] * mul[v] % mod;
    }
}

int main() {
    register int i, j, c, x, u, v;
    n = read();
    for (i = 1; i <= n; ++i) a[i] = read();
    m = read();
    for (i = 1; i <= m; ++i) {
        tpy[i] = read();
        if (tpy[i] == 1) pos[i] = read(), val[i] = read();
        else if (tpy[i] == 2) val[i] = read();
        else {
            c = read();
            for (j = 1; j <= c; ++j) x = read(), e[i].push_back(x), deg[x]++;
        }
    }
    for (i = 1; i <= m; ++i) if (!vis[i] && !deg[i]) dfs(i);
    Q = read(); for (i = 1; i <= Q; ++i) q[i] = read();
    mult = 1;
    for (i = Q; i > 0; --i) {
        if (tpy[q[i]] == 1) f[q[i]] = (f[q[i]] + mult) % mod;
        else if (tpy[q[i]] == 2) mult = 1ll * mult * val[q[i]] % mod;
        else f[q[i]] = (f[q[i]] + mult) % mod, mult = 1ll * mult * mul[q[i]] % mod;
    }
    for (i = 1; i <= m; ++i) if (!deg[i]) que.push(i);
    while (!que.empty()) {
        u = que.front(); que.pop();
        if (tpy[u] == 1) add[pos[u]] = (add[pos[u]] +  1ll * val[u] * f[u] % mod) % mod;
        
        int res = f[u];
        for (j = (int) e[u].size() - 1; j >= 0; --j) {
            v = e[u][j];
            if (--deg[v] == 0) que.push(v);
            f[v] = (f[v] + res) % mod, res = 1ll * res * mul[v] % mod;
        }
        
    }
    for (i = 1; i <= n; ++i) printf("%lld ", (1ll * a[i] * mult + add[i]) % mod);
    return 0;
}
posted @ 2020-11-12 21:09  zfio  阅读(157)  评论(1编辑  收藏  举报