icpc2020济南站

A Matrix Equation

  • 利用列相互独立,将题目公式化简即可
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <bitset>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uii;
typedef pair<int, int> pii;
template<typename T>
inline void rd(T& x)
{
    
    
	int tmp = 1; char c = getchar(); x = 0;
	while (c > '9' || c < '0') {
    
     if (c == '-')tmp = -1; c = getchar(); }
	while (c >= '0' && c <= '9') {
    
     x = x * 10 + c - '0'; c = getchar(); }
	x *= tmp;
}
ll gcd(ll x, ll y) {
    
    
	if (y == 0) return x;
	return gcd(y, x % y);
}
const int N = 1e3 + 10;
const int M = 1e7 + 10;
const int mod = 998244353;
const ull seed = 31;
const double eps = 1e-10;
int sgn(double x) {
    
    
	if (fabs(x) <= eps) return 0;
	if (x > 0) return 1;
	return -1;
}
int head[N], cntE = 0;
struct edge {
    
    
	int next, to;
	double w;
}e[M];
void add(int u, int v, double w = 0) {
    
    
	e[cntE].to = v;
	e[cntE].next = head[u];
	e[cntE].w = w;
	head[u] = cntE++;
}
int n, m, k;
int A[202][202], B[202][202];
bitset<202>a[202];
int gauss(int n) {
    
    
	int res = 0;
	for (int i = 1, p = 1; i <= n; i++) {
    
    
		int m = p;
		if (!a[m][i]) {
    
    
			for (int j = p + 1; j <= n; j++) {
    
    
				if (a[j][i]) {
    
    
					m = j;
					break;
				}
			}
		}
		if (!a[m][i]) {
    
    
			continue;
		}
		if (p != m)swap(a[p], a[m]);
		for (int j = p + 1; j <= n; j++) {
    
    
			if (a[j][i]) {
    
    
				a[j] ^= a[p];
			}
		}
		++res;
		p++;
	}
	return res;
}
ll fp(ll x, ll y) {
    
    
	ll ans = 1;
	while (y) {
    
    
		if (y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans;
}
int main() {
    
    
#ifdef _DEBUG
	FILE* _INPUT = freopen("input.txt", "r", stdin);
	//	FILE* _OUTPUT = freopen("output.txt", "w", stdout);
#endif // !_DEBUG
	int cas = 0, T = 1;
//	rd(T);
//	while (T--) {
    
    
	while (~scanf("%d",&n)) {
    
    
		for (int i = 1; i <= n; ++i) {
    
    
			for (int j = 1; j <= n; ++j) rd(A[i][j]);
		}
		for (int i = 1; i <= n; ++i) {
    
    
			for (int j = 1; j <= n; ++j) {
    
    
				rd(B[i][j]);
			}
		}
		int ans = 0;
		for (int k = 1; k <= n; ++k) {
    
    
			for (int i = 1; i <= n; ++i) {
    
    
				for (int j = 1; j <= n; ++j) a[i][j] = A[i][j];
				a[i][i] = a[i][i] ^ B[i][k];
			}
			ans += n - gauss(n);
		}
		ll res = fp(2, ans);
		printf("%lld\n", res);
	}
	return 0;
}

C Stone Game

  • 考虑正常而言将①和②进行合成会更优
  • 考虑一个特判,例如当①有3个以及②只有一个的情况
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
    
    
	ll x, y, z;
	scanf("%lld %lld %lld", &x, &y, &z);
	ll ans = 0;
	ll tmp = (x / 3, y / 3);
	ans += 1LL * tmp * 6;
	x -= 3 * tmp;
	y -= 3 * tmp;
	if (x > y && y == 1 && x % 3 == 0) {
    
    
		ans += x;
	}
	else {
    
    
		tmp = min(x, y);
		ans += 1LL * tmp * 2;
		x -= tmp;
		y -= tmp;
		if (x % 3 == 0) ans += x;
		else ans += x - 1;
		if (y % 3 == 0) ans += y / 3 * 6;
		else if (y % 3 == 2) ans += y / 3 * 6 + 4;
		else ans += y / 3 * 6;
	}
	printf("%lld\n", ans);
	return 0;
}

D Fight against involution

  • 考虑在同一个右端点相同的情况下排名相同
  • 并且题目要求排名可以高不能降
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
map<int, int>vis, num;
int main() {
    
    
	int n;
	scanf("%d", &n);
	for (int i = 1;i <= n;++i) {
    
    
		int l, r;
		scanf("%d %d", &l, &r);
		vis[r] = max(l, vis[r]);
		++num[r];
	}
	ll ans = 0;
	int pre = 0;
	for (auto v : vis) {
    
    
		int tmp = max(pre, v.second);
		ans += 1LL * tmp * num[v.first];
		pre = tmp;
	}
	printf("%lld\n", ans);
	return 0;
}

J Tree Constructer

  • 用二分图染色法将点标记为黑色和白色,白色为数量少一些的。
  • 将白点和黑点都分别用新的下标标记(两种颜色的点的下标是独立的),标记数组名为 i d id id
  • 白点的权值最高位和 i d id id位为 0 0 0,其余位为 1 1 1
  • 黑点的权值除了与相邻白点的 i d id id位和最高位是 1 1 1,其余均为 0 0 0

综上所述构造就可以了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const ll M = (1LL << 60) - 1;
vector<int> v[N];
int n, sum0, sum1;
int color[N];
int id[N][2];
ll a[N];
void init() {
    
    }
void dfs(int u, int fa, int c) {
    
    
	color[u] = c;
	if (c == 0)
		id[u][c] = ++sum0;
	else
		id[u][c] = ++sum1;
	for (int i = 0; i < v[u].size(); ++i) {
    
    
		if (v[u][i] == fa)
			continue;
		dfs(v[u][i], u, c ^ 1);
	}
}
void draw(int u, int fa, int flag) {
    
    
	if (flag == color[u])
		a[u] = M - (1LL << (id[u][color[u]] - 1)) - (1LL << 59);
	else if (flag != color[u] && fa != -1)
		a[u] = (1LL << (id[fa][color[fa]] - 1)) + (1LL << 59);
	else if (flag != color[u] && fa == -1)
		a[u] = (1LL << 59);
	for (int i = 0; i < v[u].size(); ++i) {
    
    
		int V = v[u][i];
		if (V == fa)
			continue;
		draw(V, u, flag);
		if (flag != color[u])
			a[u] += (1LL << (id[V][color[V]] - 1));
	}
}
int main() {
    
    
	scanf("%d", &n);
	for (int i = 1; i < n; ++i) {
    
    
		int U, V;
		scanf("%d%d", &U, &V);
		v[U].push_back(V);
		v[V].push_back(U);
	}
	dfs(1, -1, 0);
	if (sum0 >= sum1)
		draw(1, -1, 1);
	else
		draw(1, -1, 0);
	for (int i = 1; i <= n; ++i)
		printf("%lld%s", a[i], i == n ? "\n" : " ");
}

L Bit Sequence

  • 考虑到 m m m 的大小上限是100,只在低六位进行加减法,其余高位最多只+1
  • 找出对应的规律后直接数位dp即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uii;
typedef pair<int, int> pii;
template<typename T>
inline void rd(T& x)
{
    
    
	int tmp = 1; char c = getchar(); x = 0;
	while (c > '9' || c < '0') {
    
     if (c == '-')tmp = -1; c = getchar(); }
	while (c >= '0' && c <= '9') {
    
     x = x * 10 + c - '0'; c = getchar(); }
	x *= tmp;
}
ll gcd(ll x, ll y) {
    
    
	if (y == 0) return x;
	return gcd(y, x % y);
}
const int N = 2e5 + 10;
const int M = 1e7 + 10;
const int mod = 998244353;
int n, m, k;
ll x;
int a[102];
ll dp[65][130][2][2];
int digit[65];
bool check(int sta, int sum, int p) {
    
    
	for (int i = 0; i < n; ++i) {
    
    
		if (sta + i < 128) {
    
    
			if ((__builtin_parity(sta + i) ^ sum) != a[i]) return false;
		}
		else {
    
    
			if ((__builtin_parity((sta + i) & 127) ^ sum ^ (!p)) != a[i]) return false;
		}
	}
	return true;
}
ll dfs(int len, int sta, int sum, int p, bool limit) {
    
    
	if (len < 0) return check(sta, sum, p);
	if (!limit && ~dp[len][sta][sum][p]) return dp[len][sta][sum][p];
	int up = limit ? digit[len] : 1;
	ll res = 0;
	for (int i = 0; i <= up; ++i) {
    
    
		if (len >= 7) {
    
    
			res += dfs(len - 1, sta, sum ^ i, i & (!p), limit && i == up);
		}
		else res += dfs(len - 1, sta | (i << len), sum, p, limit && i == up);
	}
	if (!limit) dp[len][sta][sum][p] = res;
	return res;
}
void solve() {
    
    
	int len = 0;
	for (ll tmp = x; tmp; tmp >>= 1) {
    
    
		digit[len++] = tmp & 1;
	}
	printf("%lld\n", dfs(len - 1, 0, 0, 0, 1));
}
int main() {
    
    
#ifdef _DEBUG
	FILE* _INPUT = freopen("input.txt", "r", stdin);
	//	FILE* _OUTPUT = freopen("output.txt", "w", stdout);
#endif // !_DEBUG
	int cas = 0, T = 1;
	rd(T);
	while (T--) {
    
    
//	while (~scanf("%d",&n)) {
    
    
		rd(n); rd(x);
		for (int i = 0; i < n; ++i) rd(a[i]);
		memset(dp, -1, sizeof dp);
		solve();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bloom_er/article/details/114308192
今日推荐