CSP2020题解

虽然炸了,题解还是要补的

儒略日

没有什么好说的,直接模拟
(貌似官方数据比较水,所以飞过去了)
code:

#include<bits/stdc++.h>
#define PN 365
#define int long long
#define RN 366
#define N 5005
using namespace std;
int yue[15] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int yue2[15] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int sy[15], sy2[15], bcn[N];
int GLL, GYQ;
int NIAN, YUE, RI;
int calc(int x) {
	return x * 365 + x / 4;
}
int calcc(int x) {
	return x * 365 + x / 4 - (x / 100 - x / 400)  + 12;
}
signed main() {
//	freopen("julian.in","r",stdin);
//	freopen("julian.out","w",stdout);
	for(int i = 1; i <= 12; i ++) sy[i] = yue[i] + sy[i - 1];
	for(int i = 1; i <= 12; i ++) sy2[i] = yue2[i] + sy2[i - 1];
	for(int i = 4713; i >= 1; i --) {
		if((i - 1) % 4 == 0) bcn[i] = RN;
		else bcn[i] = PN;
	}
	for(int i = 4712; i >= 1; i --) bcn[i] += bcn[i + 1];
	GYQ = 0;
	GYQ = bcn[1];//4713 * PN + (4713 + 3) / 4 - 1;
	
	
	GLL = 0;
	for(int i = 1; i < 1582; i ++) {
		if(i % 4 == 0) GLL += RN;
		else GLL += PN;
	}
	GLL += sy2[9];
	GLL += 4;
	
	int n, t;
	scanf("%lld", &t);
	while(t --) {
		scanf("%lld", &n);
		n ++;
		if(n <= GYQ) {
			int l = 0, r = 4712;
			while(l + 1 < r) {
				int mid = (l + r) >> 1;
				if(bcn[4713 - mid] < n) l = mid;
				else r = mid;
			}
			if(bcn[4713 - l] < n) l ++;
			NIAN = 4713 - l;
			n = n - bcn[NIAN + 1];
			if((NIAN - 1)% 4 == 0) {
				for(int i = 1; i <= 12; i ++) {
					if(sy2[i] >= n) {
						YUE = i;
						break;
					}
				}
				n = n - sy2[YUE - 1];
				RI = n;
			} else {
				for(int i = 1; i <= 12; i ++) {
					if(sy[i] >= n) {
						YUE = i;
						break;
					}
				}
				n = n - sy[YUE - 1];
				RI = n;
			}
			printf("%lld %lld %lld BC\n", RI, YUE, NIAN);
		} else {
			n = n - GYQ;
			if(n <= GLL) {
				int l = 0, r = 1582;
				while(l + 1 < r) {
					int mid = (l + r) >> 1;
					if(calc(mid) >= n) r = mid;
					else l = mid;
				}
				NIAN = r;
				n = n - calc(NIAN - 1);
				
				if(NIAN % 4 == 0) {
					for(int i = 1; i <= 12; i ++) {
						if(sy2[i] >= n) {
							YUE = i;
							break;
						}
					}
					n = n - sy2[YUE - 1];
					RI = n;
				} else {
					for(int i = 1; i <= 12; i ++) {
						if(sy[i] >= n) {
							YUE = i;
							break;
						}
					}
					n = n - sy[YUE - 1];
					RI = n;
				}
				printf("%lld %lld %lld\n", RI, YUE, NIAN);	
			} else { //printf("*");
				//printf("%lld %lld\n", n, GLL);
				n += 10;
				int l = 1581, r = 1e9 + 3;
				while(l + 1 < r) {
					int mid = (l + r) >> 1;
					if(calcc(mid) >= n) r = mid;
					else l = mid;
				}
				NIAN = r;
				n = n - calcc(NIAN - 1);
				
				if((NIAN % 4 == 0 && NIAN % 100 != 0) || (NIAN % 400 == 0)) {
					for(int i = 1; i <= 12; i ++) {
						if(sy2[i] >= n) {
							YUE = i;
							break;
						}
					}
					n = n - sy2[YUE - 1];
					RI = n;
				} else {
					for(int i = 1; i <= 12; i ++) {
						if(sy[i] >= n) {
							YUE = i;
							break;
						}
					}
					n = n - sy[YUE - 1];
					RI = n;
				}
				printf("%lld %lld %lld\n", RI, YUE, NIAN);
				
			}
			
		}	
	}
	
	return 0;
}

动物园

好像耶没什么难度吧
code:

#include<bits/stdc++.h>
#define N 1000005
#define ull unsigned long long
using namespace std;
struct Q {
	int x, y;
} q[N];
int n, m, c, k, col[85], anss[85], tot, sl[N];
ull a[N];
ull read() {
	ull x = 0;
	char ch = getchar();
	for(;ch <'0' || ch > '9';) ch = getchar();
	for(;ch >= '0' && ch <= '9';) x = x * 10 + (ch - '0'), ch = getchar();
	return x;
}
int main() {
	//scanf("%d%d%d%d", &n, &m, &c, &k);
//	freopen("zoo.in","r",stdin);
	//freopen("zoo.out","w",stdout);
	ios::sync_with_stdio(false);
	n = read(), m = read(), c = read(), k = read();
	for(int i = 1; i <= n; i ++) {
		a[i] = read();
		ull x = a[i];
		for(int i = 0; i < k; i ++) {
			if((x >> i) & 1) col[i] = 1;
		}
	}
	for(int i = 1; i <= m; i ++) {
		int x, y;
		x = read(), y = read();
		q[i].x = x, q[i].y = y;
		if(col[x]) sl[++ tot] = y;
	}
	sort(sl + 1, sl + 1 + tot);
	for(int i = 1; i <= m; i ++) {
		int x = q[i].x, y = q[i].y;
		if(!col[x]) {
			int pos = lower_bound(sl + 1, sl + 1 + tot, y) - sl;
			if(sl[pos] != y) {
				anss[x] = 1;
			}
		}
	}
	ull ans = 1, ss = 0;
	for(int i = 0; i < k; i ++)
		if(!anss[i]) ans = ans * 2, ss ++;
	ans = ans - n;
	if(ss == 64 && !n) cout << "18446744073709551616";
	else cout << ans;
	return 0;
}

函数调用

考场上一直在刚最后一题,这题只花了5min写了个暴力
考完发现还是一个挺妙的题
首先考虑一个加法操作 + a +a +a,如果后面有一个乘法操作 ∗ b *b b,那就相当于加上了 + a ∗ b +a*b +ab
m l [ i ] ml[i] ml[i]为第i个操作做完后所有数被乘了多少,最后肯定是所有数 ∗ m l [ m + 1 ] + 某 个 值 *ml[m+1]+某个值 ml[m+1]+
那个值就是所有在那个位置的加法产生的贡献,记 p a d [ i ] pad[i] pad[i]表示第 i i i个操作如果对之前的操作的加法产生的乘法贡献(后面的乘法贡献之和)
然后这个操作加的值就是 v ∗ p a d [ i ] v* pad[i] vpad[i]
p a d [ i ] pad[i] pad[i]就是所有后缀乘的和(拓扑图上的)
然后直接拓扑排序

code:

#include<bits/stdc++.h>
#define N 2000005
#define int long long
#define mod 998244353
using namespace std;
int n, m, ml[N], a[N], pad[N], vis[N], in[N], ad[N];
vector<int> g[N], pml[N];
queue<int> qq;
struct Q {
	int opt, pos, v;
} q[N];
void dfs(int u) {
	vis[u] = 1;
	ml[u] = (q[u].opt == 2)? ml[u] = q[u].v : 1;
	for(int i = 0; i < g[u].size(); i ++) {
		pml[u].push_back(ml[u]);
		int v = g[u][i];
		if(!vis[v]) dfs(v);
		 ml[u] = ml[u] * ml[v] % mod;
	}
}
void tuopu() {
	for(int i = 1; i <= m + 1; i ++) if(vis[i])
		for(int j = 0; j < g[i].size(); j ++) {
			int v = g[i][j];
			in[v] ++;
		}	
	for(int i = 1; i <= m + 1; i ++) if(!in[i] && vis[i]) qq.push(i), pad[i] = 1;
	while(qq.size()) {
		int u = qq.front(); qq.pop();
		if(q[u].opt == 1) 
			(ad[q[u].pos] += q[u].v * pad[u] % mod) %= mod;
		for(int i = 0; i < g[u].size(); i ++) {
			int v = g[u][i];
			(pad[v] += pad[u] * pml[u][i] % mod) %= mod;
			if(!(-- in[v])) qq.push(v);
		}
	}
}
signed main() {
	scanf("%lld", &n);
	for(int i = 1; i <= n; i ++) scanf("%lld", &a[i]);
	scanf("%lld", &m);
	for(int i = 1; i <= m + 1; i ++) {
		if(i <= m) scanf("%lld", &q[i].opt);
		else q[i].opt = 3;
		if(q[i].opt == 1) scanf("%lld%lld", &q[i].pos, &q[i].v);
		else if(q[i].opt == 2) scanf("%lld", &q[i].v);
		else {
			int k;
			scanf("%lld", &k);
			while(k --) {
				int x = 0;
				scanf("%lld", &x);
				g[i].push_back(x);
			}
		}
	}
	for(int i = 1; i <= m + 1; i ++) reverse(g[i].begin(), g[i].end());
	ml[m + 1] = 1; dfs(m + 1);
	tuopu();
	for(int i = 1; i <= n; i ++) printf("%lld ", (a[i] * ml[m + 1] % mod + ad[i]) % mod);
	return 0;
}

贪吃蛇

在这里插入图片描述
摘自:https://www.luogu.com.cn/blog/wcsb/solution-p7078
推出了一些简单的性质后模拟这个过程就行了
code:

#include<bits/stdc++.h>
#define N 2000005
#define mp make_pair
#define pr pair<int, int>
using namespace std;
deque<pair<int, int> > q1, q2;
int n, a[N], t;
pr mx() {//取最大
	pr o;
	if(!q2.size() || q1.size() && q1.back() > q2.back()) o = q1.back(), q1.pop_back();
	else o = q2.back(), q2.pop_back();
	return o;
}
int main() {
	scanf("%d", &t);
	for(int cas = 1; cas <= t; cas ++) {
		while(q1.size()) q1.pop_back();
		while(q2.size()) q2.pop_back();
		int k;
		scanf("%d", &k);
		if(cas == 1) n = k;
		if(cas == 1) for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
		else {
			for(int i = 1; i <= k; i ++) {
				int x, y;
				scanf("%d%d", &x, &y);
				a[x] = y;
			}
		}
		for(int i = 1; i <= n; i ++) q1.push_back(mp(a[i], i));
		int ans = 0;
		while(1) {
			if(q1.size() + q2.size() == 2) {
				ans = 1;
				break;
			}
			int x = 0, id = 0, y = 0;
			y = q1.front().first, q1.pop_front();
			pr o = mx();
			x = o.first, id = o.second;
			pr now = mp(x - y, id);
			if(!q1.size() || q1.front() > now) {//第二阶段
				ans = q1.size() + q2.size() + 2;
				int dep = 0;
				while(1) {
					dep ++;
					if(q1.size() + q2.size() == 1) {
						ans -= !(dep & 1);
						break;
					}
					pr o = mx();
					int x = o.first, id = o.second;
					now = mp(x - now.first, id);
					if((!q1.size() || now < q1.front()) && (!q2.size() || now < q2.front())) {
						;
					} else {
						ans -= !(dep & 1);
						break;
					}
				}
				break;
			} else {
				q2.push_front(now);//第一阶段
			}
		}
		printf("%d\n", ans);	
	}
	
	return 0;
}

总体来说题目质量还行吧

posted @ 2020-12-01 15:38  lahlah  阅读(32)  评论(0编辑  收藏  举报