PKU-CPC 2019 简要题解

有的代码是现场写的可能比较难看,懒得改了……凑合看下吧。
找时间补补

A. Ball

分类讨论。

#include <bits/stdc++.h>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

struct Disjoint_Set_Union
{
	int father[200005];
	int size[200005];
	int edge[200005];
	int F[200005];
	
	void reset(int n)
	{
		for(int i = 1; i <= n; i++)
			father[i] = i;
		
		fill(&size[1], &size[n]+1, 1);
		fill(&edge[1], &edge[n]+1, 0);
		fill(&F[1], &F[n]+1, 0);
	}
	
	int get_root(int i)
	{
		if(father[i] == i)
			return i;
		else
			return father[i] = get_root(father[i]);
	}
};

int main()
{
#ifndef ONLINE_JUDGE
	freopen("test.in", "r", stdin);
#endif
	const int P = 10000019;
	
	int t;
	scanf("%d", &t);
	
	static Disjoint_Set_Union dsu;
	static bool vis[200005];
	for(int _ = 1; _ <= t; _++) {
		int n, m;
		scanf("%d%d", &n, &m);
		
		dsu.reset(m);
		for(int _ = 1; _ <= n; _++) {
			int a, b;
			scanf("%d%d", &a, &b);
			
			if(a == b) {
				dsu.edge[dsu.get_root(a)]++;
				dsu.F[dsu.get_root(a)]++;
			}
			
			else if(dsu.get_root(a) == dsu.get_root(b)) {
				a = dsu.get_root(a);
				
				dsu.edge[a]++;
			}
			
			else {
				a = dsu.get_root(a);
				b = dsu.get_root(b);
				
				dsu.father[b] = a;
				dsu.size[a] += dsu.size[b];
				dsu.edge[a] += dsu.edge[b] + 1;
				dsu.F[a] += dsu.F[b];
			}
		}
		
		fill(&vis[0], &vis[m]+1, false);
		int ans = 1;
		
		for(int i = 1; i <= m; i++)
		if(! vis[dsu.get_root(i)]) {
			int j = dsu.get_root(i);
			vis[j] = true;
			
			if(dsu.edge[j] > dsu.size[j])
				ans = 0;
			
			else if(dsu.edge[j] == dsu.size[j] && ! dsu.F[j])
				ans = ans * 2 % P;
			
			else if(dsu.edge[j] == dsu.size[j] && dsu.F[j])
				ans = ans;
			
			else
				ans = (long long)ans * dsu.size[j] % P;
		}
		
		printf("%d\n", ans);
	}
}

B. Seal

C. Parade

类似均分纸牌,一个方向扫过去支付代价。

#include <bits/stdc++.h>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

const int N = 100010;

int cnt[N][2];

void solve() {
    memset(cnt, 0, sizeof(cnt));
    ll ans = 0;
    int n;
    scanf("%d", &n);
    for (int rep = 0; rep < n * 2; ++rep) {
        int x, y;
        scanf("%d%d", &x, &y);
        if (y < 1) {
            ans += 1 - y;
            y = 1;
        }
        if (y > 2) {
            ans += y - 2;
            y = 2;
        }
        if (x < 1) {
            ans += 1 - x;
            x = 1;
        }
        if (x > n) {
            ans += x - n;
            x = n;
        }
        ++cnt[x][y - 1];
    }
    for (int i = 1; i <= n; ++i) {
#define A cnt[i][0]
#define B cnt[i][1]
        --A;
        --B;
        if (A > 0 && B > 0) {
            ans += A + B;
            cnt[i + 1][0] += A;
            cnt[i + 1][1] += B;
        } else if (A <= 0 && B <= 0) {
            ans -= A + B;
            cnt[i + 1][0] += A;
            cnt[i + 1][1] += B;
        } else if (A <= 0 && B > 0) {
            if (-A > B) {
                ans += B;
                A += B;
                ans += abs(A);
                cnt[i + 1][0] += A;
            } else {
                ans += -A;
                B += A;
                ans += abs(B);
                cnt[i + 1][1] += B;
            }
        } else if (A > 0 && B <= 0) {
            if (A > -B) {
                ans += -B;
                A += B;
                ans += abs(A);
                cnt[i + 1][0] += A;
            } else {
                ans += A;
                B += A;
                ans += abs(B);
                cnt[i + 1][1] += B;
            }
        }
    }
    printf("%lld\n", ans);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
#endif
	int t;
	scanf("%d",&t);
	while(t--)
    	solve();
}

D. Circuit

FWT 板子。

#include <bits/stdc++.h>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

const int N = 15;

int n, p, P;
int a[(1 << N) + 10], b[(1 << N) + 10];

int norm(int x) { return x >= p ? x - p : x; }

int Norm(int x) { return x >= P ? x - P : x; }

void fwt(int* a) {
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < 1 << n; ++j)
			if (!(j >> i & 1)) {
				int a0 = a[j], a1 = a[j | 1 << i];
				a[j] = Norm(a0 + a1);
				a[j | 1 << i] = Norm(a0 - a1 + P);
			}
}

void deb(int* a) {
	for (int i = 0; i < 1 << n; ++i)
		LOG("%d ", a[i]);
	LOG("\n");
}

void solve() {
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	int x, y, z;
	scanf("%d%d%d%d%d", &n, &x, &y, &z, &p);
	P = p << n;
	while (x--) {
		int l, r, c;
		scanf("%d%d%d", &l, &r, &c);
		c = norm(c % p + p);
		a[l] = norm(a[l] + c);
		a[r + 1] = norm(a[r + 1] - c + p);
	}
	for (int i = 1; i < 1 << n; ++i) a[i] = norm(a[i] + a[i - 1]);
	while (y--) {
		int l, r, c;
		scanf("%d%d%d", &l, &r, &c);
		c = norm(c % p + p);
		b[l] = norm(b[l] + c);
		b[r + 1] = norm(b[r + 1] - c + p);
	}
	for (int i = 1; i < 1 << n; ++i) b[i] = norm(b[i] + b[i - 1]);
	fwt(a);
	fwt(b);
	for (int i = 0; i < 1 << n; ++i) a[i] = a[i] * (ll)b[i] % P;
	fwt(a);
	for (int i = 0; i < 1 << n; ++i) a[i] >>= n;
	for (int i = 1; i < 1 << n; ++i) a[i] = norm(a[i] + a[i - 1]);
	while (z--) {
		int l, r;
		scanf("%d%d", &l, &r);
		int ans = a[r];
		if (l)
			ans = norm(ans - a[l - 1] + p);
		printf("%d ", ans % p);
	}
	putchar('\n');
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("test.in", "r", stdin);
#endif

	int t;
	scanf("%d", &t);
	while (t--)
		solve();
}

E. Coprime

容斥一下,vector 上二分。

#include <bits/stdc++.h>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

const int N = 100010;

int n, m;
int a[N], mu[N];
vector<int> fac[N], ex[N];

void pre(int n) {
	mu[1] = 1;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + i; j <= n; j += i)
			mu[j] -= mu[i];
	}
	for (int i = 1; i <= n; ++i) {
		if (!mu[i]) continue;
		for (int j = i; j <= n; j += i)
			fac[j].push_back(i);
	}
}

void solve() {
	fill(ex + 1, ex + 100001, vector<int>());
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		int x;
		scanf("%d", &x);
		for (int v : fac[x])
			ex[v].push_back(i);
	}
	int d = 0;
	while (m--) {
		int l, r, x;
		scanf("%d%d%d", &l, &r, &x);
		l ^= d; r ^= d; x ^= d;
		d = 0;
		for (int v : fac[x])
			d += mu[v] * (int)(upper_bound(ex[v].begin(), ex[v].end(), r) - lower_bound(ex[v].begin(), ex[v].end(), l));
		printf("%d\n", d);
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("test.in", "r", stdin);
#endif
	pre(100000);
	int t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
}

F. Graduation

暴力。

#include <bits/stdc++.h>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

struct Time
{
	int day;
	int l, r;
};

int main()
{
#ifndef ONLINE_JUDGE
	freopen("test.in", "r", stdin);
#endif
	
	int t;
	scanf("%d", &t);
	
	for(int _ = 1; _ <= t; _++) {
		int already[6];
		for(int i = 1; i <= 5; i++)
			scanf("%d", &already[i]);
		
		int goal[6];
		for(int i = 1; i <= 5; i++) {
			scanf("%d", &goal[i]);
			goal[i] = max(goal[i] - already[i], 0);
		}
		
		int n;
		scanf("%d", &n);
		
		int id[11], type[11], d[11];
		vector<Time> time[11];
		for(int i = 1; i <= n; i++) {
			int k;
			scanf("%d%d%d%d", &id[i], &type[i], &d[i], &k);
			
			for(int _ = 1; _ <= k; _++) {
				int day, l, r;
				scanf("%d%d%d", &day, &l, &r);
				
				time[i].push_back({day, l, r});
			}
		}
		
		if(goal[1] + goal[2] + goal[3] + goal[4] + goal[5] > 25)
			printf("unable to graduate\n");
		
		else if(goal[1] == 0 && goal[2] == 0 && goal[3] == 0 && goal[4] == 0 && goal[5] == 0)
			printf("able to graduate\n");
		
		else {
			vector<int> ans(100);
			for(int sn = 2; sn < 1<<n+1; sn += 2) {
				int cnt[6] = {};
				for(int i = 1; i <= n; i++)
				if(sn & (1<<i))
					cnt[type[i]]++;
				
				if(cnt[3] > 1 || cnt[4] > 1 || cnt[5] > 1)
					continue;
				
				if(cnt[1] + cnt[2] + cnt[3] + cnt[4] + cnt[5] >= ans.size())
					continue;
				
				//----------------------------------//
				
				int score[6] = {};
				for(int i = 1; i <= n; i++)
				if(sn & (1<<i))
					score[type[i]] += d[i];
				
				if(score[1] + score[2] + score[3] + score[4] + score[5] > 25)
					continue;
				
				if(score[1] < goal[1] || score[2] < goal[2] || score[3] < goal[3] || score[4] < goal[4] || score[5] < goal[5])
					continue;
				
				//----------------------------------//
				
				bool vis[7][13] = {};
				for(int i = 1; i <= n; i++)
				if(sn & (1<<i))
				for(auto t : time[i])
				for(int i = t.l; i <= t.r; i++) {
					if(vis[t.day][i])
						goto TAG;
					else
						vis[t.day][i] = true;
				}
				
				ans.clear();
				for(int i = 1; i <= n; i++)
				if(sn & (1<<i))
					ans.push_back(id[i]);
				
				TAG:;
			}
			
			if(ans.size() >= 98)
				printf("unable to graduate\n");
			
			else {
				sort(ans.begin(), ans.end());
				
				printf("able to graduate\n");
				for(auto i : ans)
					printf("%d ", i);
				printf("\n");
			}
		}
	}
}

G. Go and Oreo

H. Homomorphism

I. Chamber of Braziers

J. Matrix of Determinants

K. Winner Winner, Chicken Dinner!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值