zoukankan      html  css  js  c++  java
  • 「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
    ");
        else
            printf("
    ");
    }
    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
    ", 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;
    }
    
  • 相关阅读:
    Java集合(二)-Set集合
    Java集合类
    Java构造器和初始化块
    学习OpenStack-Neutron网络服务
    Error response from daemon: Get https://index.docker.io/v1/search?q=tomcat&n=25: net/http: TLS handshake timeout
    学习OpenStack-Nova计算服务
    学习OpenStack-Glance组件部署
    报错:rsync同步报错
    报错:创建nginx镜像时出现报错
    报错:重启Docker报错如何解决
  • 原文地址:https://www.cnblogs.com/Zfio/p/13966286.html
Copyright © 2011-2022 走看看