codeforces Good Bye 2022: 2023 is NEAR C-D

Good Bye 2022: 2023 is NEAR

C. Koxia and Number Theory

判断一个长度为n的正整数数组是否存在一个大于0的数x使得任意 1 ≤ i < j ≤ n 1 \leq i \lt j \leq n 1i<jn

g c d ( a i + x , a j + x ) = 1 gcd(a_i + x, a_j + x) = 1 gcd(ai+x,aj+x)=1

数据范围: 2 ≤ n ≤ 100 , 1 ≤ a i ≤ 1 0 18 2 \leq n \leq 100, 1 \leq a_i \leq 10^{18} 2n100,1ai1018

  1. 如果 a i a_i ai不是两两不同的, 那么答案为false
  2. 对于一个质数P, 令 c n t j cnt_j cntj j j j [ a 1 m o d p , a 2 m o d p , . . . a n m o d p ] [a_1\quad mod\quad p, a_2\quad mod\quad p, ...a_n\quad mod\quad p] [a1modp,a2modp,...anmodp]中出现的次数,如果min( c n t 0 , c n t 1 , . . . , c n t p − 1 ≥ 2 cnt_0, cnt_1, ...,cnt_{p- 1}\geq2 cnt0,cnt1,...,cntp12), 则该情况为false
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <set>


using namespace std;
using ll = long long;

const int N = 110;
int n;
ll a[N];
int cnt[N];

void solve() {
	scanf("%d", &n);
	for(int i = 0; i < n; i++) {
		scanf("%lld", &a[i]);
	}
	sort(a, a + n);
	for(int i = 1; i < n; i++) {
		if(a[i] == a[i - 1]) {
			return puts("NO"), void();
		}
	}
	for(int mod = 2; mod <= n / 2; mod ++) {
		fill(cnt, cnt + mod, 0);
		for(int i = 0; i < n; i++) {
			cnt[a[i] % mod]++;
		}
		if(*min_element(cnt, cnt + mod) >= 2) {
			return puts("NO"), void();
		}
	}
	puts("YES");

}


int main() {
	// freopen("in.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while(t--) solve();
	return 0;
}

D. Koxia and Game

  1. 只有每一轮 d i d_i di对于 M a h i r u Mahiru Mahiru都只有一种选择时, K o x i a Koxia Koxia才可能获胜
  2. 令P是一个长度为n的数组, 其中 P i P_i Pi a i a_i ai b i b_i bi中的一者, K o x i a Koxia Koxia获胜当且仅当p可能是一个排列
    • 当P可能是一个排列时,令 c i c_i ci = p i p_i pi, 使得 M a h i r u Mahiru Mahiru在每一轮中都选择 d i = p i d_i = p_i di=pi, 所以 K o x i a Koxia Koxia获胜
    • 当P不可能是一个排列时, 则不存在c使得 K o x i a Koxia Koxia获胜
  3. 需要一个算法判定P是否可能是一个排列
    1. a i 和 b i a_i 和 b_i aibi连接一条无向边, 如果存在连通块的边和点的数量不同时,则无解,见样例二
    2. 每一个边等于点的连通分量可以当作一棵树加上一条附加边
      1. 附加边与其他树边形成环, 此时有两种边选点的方案
      2. 附加边形成自环,此时可选的方案为n
#include <iostream>
#include <algorithm>
#include <cstdio>


using namespace std;
using ll = long long;

const int N = 1e5 + 10, MOD = 998244353;
int n;
int a[N], b[N], f[N], cntV[N], cntE[N], selfLoop[N];

void init() {
	for(int i = 1; i <= n; i++) {
		f[i] = -1;
		cntV[i] = 1;
		cntE[i] = 0;
		selfLoop[i] = 0;
	}
}

int find(int x) {
	return f[x] < 0 ? x : f[x] = find(f[x]);
}

void merge(int x, int y) {
	int fx = find(x), fy = find(y);
	if(f[fx] < f[fy]) {
		f[fx] += f[fy], f[fy] = fx;
		cntV[fx] += cntV[fy];
		cntE[fx] += cntE[fy];
		selfLoop[fx] |= selfLoop[fy];
	} else {
		f[fy] += f[fx], f[fx] = fy;
		cntV[fy] += cntV[fx];
		cntE[fy] += cntE[fx];
		selfLoop[fy] |= selfLoop[fx];
	}
}

void solve() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
	init();
	for(int i = 1; i <= n; i++) {
		if(find(a[i]) != find(b[i])) {
			merge(a[i], b[i]);
		}
		cntE[find(a[i])]++;
		if(a[i] == b[i]) selfLoop[find(a[i])] = 1;
	}
	ll res = 1ll;
	for(int i = 1; i <= n; i++) {
		if(f[i] < 0) {
			if(cntV[find(i)] != cntE[find(i)]) {
				return puts("0"), void();
			}
			res = res * (selfLoop[find(i)] ? n : 2) % MOD;
		}
	}
	printf("%lld\n", res);
}


int main() {
	// freopen("in.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while(t--) solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值