比赛链接:http://codeforces.com/contest/869

A. The Artful Expedient

题意:给你一个n,分别输入两组n个数字,,如果这两组数字两两异或的结果与两组数字中的某一个数字相等,那么就有1个pair满足要求,如果最后结果是偶数个pair,那么就是Karen赢,否则是KOYOMI赢

解法:暴力。实际上,这个题是不可能出现奇数对的情况的,直接输出"Karen"就可以了。

#include <bits/stdc++.h>
using namespace std;
int a[2010], b[2010];
bool vis[2000010];
int main(){
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++) scanf("%d", &a[i]), vis[a[i]]=1;
    for(int i=1; i<=n; i++) scanf("%d", &b[i]), vis[b[i]]=1;
    int ans = 0;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            if(vis[a[i]^a[j]]){
                if(i==j)ans++;
                else ans+=2;
            }
        }
    }
    if(ans%2==0){
        puts("Karen");
    }
    else{
        puts("Koyomi");
    }
    return 0;
}

B. The Eternal Immortality

题意:计算b!/a!的最后一个数字。

解法:实际上就是从a+1算到b,但是没必要真的算到b,我们算到a+20肯定会出现末尾0的情况,所以就for一遍就行了。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
	LL a, b;
	cin >> a >> b;
	LL sum = 1;
	for (LL i = a + 1; i <= min(b, a + 20); i++)
	{
		LL t = i % 10;
		sum *= t;
		sum %= 10;
	}
	printf("%lld\n", sum);
	return 0;
}


C. The Intriguing Obsession

题意:有3种不同颜色的点分别有a,b,c个。要求我们连边,任意相同的点要么不能直接连边,要么它们的距离大于等于3。

解法:根据样例,大概可以猜测是a,b之间的方案数,b,c之间的方案数,a,c之间的方案数的乘积。关键是如何计算a,b之间的方案数,考虑从a,b里面选i个出来,那么i最多到min(a,b),有C(i,a)*C(i,b),这i个可以任意排列,所以有i!种方案,因此一共有sigma(i!*C(i,a)*C(i,b))种方案。


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5005;
const int mod = 998244353;
LL c[maxn][maxn];
LL fac[maxn];

LL cal(int n, int m)
{
	if (n < m) swap(n, m);
	LL ret = 0;
	for (int i = 0; i <= m; i++)
	{
		ret += fac[i] * c[n][i] % mod * c[m][i] % mod;
		ret %= mod;
	}
	return ret;
}

int main()
{
	c[0][0] = 1;
	for (int i = 1; i <= 5000; i++)
	{
		c[i][0] = 1;
		for (int j = 1; j <= i; j++)
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
	}
	fac[0] = 1LL;
	fac[1] = 1LL;
	for (LL i = 2; i <= 5000; i++) fac[i] = fac[i - 1] * i % mod;
	LL x, y, z;
	cin >> x >> y >> z;
	LL ans = 1;
	ans = ans * cal(x, y) % mod;
	ans = ans * cal(x, z) % mod;
	ans = ans * cal(z, y) % mod;
	printf("%lld\n", ans);
	return 0;
}


D:还没补。


E. The Untended Antiquity

题意:二维平面上,我们有3种操作,加矩形栅栏,删除矩形栅栏,询问2个点是否连通。

解法:二维树状数组维护一下矩形的和,最后通过对查询点的左上方求和,加和删就对应树状数组的更新。发现和相同就是Yes,否则就是No,但是坑点是这题给每个矩形加1个值的时候,这个值要随机生成,不然会被轻易卡WA。


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2520;
LL c[maxn][maxn];
map<pair<pair<int, int>, pair<int, int> >, LL> mp;
int n, m, q;

int lowbit(LL x)
{
	return x & -x;
}

void add(int x, int y, LL z)
{
	for (int i = x; i <= n; i += lowbit(i))
		for (int j = y; j <= m; j += lowbit(j))
			c[i][j] += z;
}

LL sum(int x, int y)
{
	LL ret = 0;
	for (int i = x; i > 0; i -= lowbit(i))
		for (int j = y; j > 0; j -= lowbit(j))
			ret += c[i][j];
	return ret;
}


LL rnd()
{
	return ((LL)rand() << 48) | ((LL)rand() << 32) | ((LL)rand() <<16) | (LL)rand();
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	srand(time(NULL));
	for (int i = 0; i < q; i++)
	{
		int op, x1, y1, x2, y2;
		scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2);
		if (op == 1)
		{
			LL u = rnd();
			mp[make_pair(make_pair(x1, y1), make_pair(x2, y2))] = u;
			add(x1, y1, u);
			add(x1, y2 + 1, -u);
			add(x2 + 1, y1, -u);
			add(x2 + 1, y2 + 1, u);
		}
		else if (op == 2)
		{
			LL u = mp[make_pair(make_pair(x1, y1), make_pair(x2, y2))];
			add(x1, y1, -u);
			add(x1, y2 + 1, u);
			add(x2 + 1, y1, u);
			add(x2 + 1, y2 + 1, -u);
		}
		else
		{
			LL a = sum(x1, y1);
			LL b = sum(x2, y2);
			if (a == b) puts("Yes");
			else puts("No");
		}
	}
	return 0;
}