【比赛】 Codeforces Round #697 (Div. 3)

题目来源

【比赛】 Codeforces Round #697 (Div. 3)

A Odd Divisor

如果其因子有奇数的话,那么必不会被2整除,利用这个特点进行检查即可。

#include<iostream>
#include<vector>
#include<queue>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= (b); --i)
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> IntVec;

bool check(ll x)
{
	while (x > 1)
	{
		if (x & 1) return true;
		x >>= 1;
	}
	return false;
}

const int N = 200 + 10, INF = 0x3f3f3f3f;
int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin.tie(0);

	int T;
	cin >> T;
	while (T--)
	{
		ll x;
		cin >> x;
		if (check(x)) puts("YES");
		else puts("NO");
	}

	return 0;
}

B - New Year’s Number

只要判断除以2020后剩余的1够不够分配即可。

#include<bits/stdc++.h>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= (b); --i)
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> IntVec;

const int N = 200 + 10, INF = 0x3f3f3f3f;


int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin.tie(0);

	int T;
	cin >> T;
	while (T--)
	{
		ll x;
		cin >> x;
		if (x / 2020 < x % 2020) puts("NO");
		else puts("YES");
	}
	return 0;
}

C - Ball in Berland

利用容斥原理进行排除,总的情况减去男生重复情况减去女生重复情况,加上男女重复情况。

#include<bits/stdc++.h>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= (b); --i)
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> IntVec;

const int N = 200000 + 10, mod = 1e9 + 7;
int a[N], b[N];
map<int, int> cnta, cntb;
map<pii, int> cntab;

ll cal(ll x)
{
	return x * (x - 1) / 2;
}

int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin.tie(0);
	
	int T;
	cin >> T;
	while (T--)
	{
		cnta.clear();
		cntb.clear();
		cntab.clear();
		int n, m, k;
		cin >> n >> m >> k;
		_for(i, 0, k) cin >> a[i];
		_for(i, 0, k) cin >> b[i];
		ll ans = cal(k * 1ll);
		_for (i, 0, k)
		{
			cnta[a[i]]++;
			cntb[b[i]]++;
			cntab[{a[i], b[i]}]++;
		}
		
		for (const auto& p : cnta) if (p.second > 1)  ans -= cal(p.second * 1ll);
		for (const auto& p : cntb) if (p.second > 1)  ans -= cal(p.second * 1ll);
		for (const auto& p : cntab) if (p.second > 1)
			ans += cal(p.second * 1ll);
		cout << ans << endl;
	}
	return 0;
}

D - Cleaning the Phone

题目大意是在n个应用中删去内存和大于的等于m并且重要程度总和小的几个应用 。
注意条件,b的取值只有1和2,所以我们可以分类讨论为:有1 的情况、有2 的情况和有1、2的情况。
这个题目我刚开始抓住的点时等于m值,重点搞错了, 题目要的就是重要程度的总和, 只要内存大于等于m就够了,最矛盾的点在于重要程度。
有两个变量在动,所以我们得想一个办法将一方固定住,让一方变, 我们可以使用前缀和的方法(遇到算数字总和的,尝试着往前缀和想)。
我们让重要程度为1 的数量变化,通过重要程度为1 的数量去二分查找最小到重要程度为2的数量。

#include<bits/stdc++.h>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= (b); --i)

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 200000 + 10, INF = 0x3f3f3f3f;
int a[N];
ll suma[N], sumb[N];

int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	int T;
	cin >> T;
	while (T--)
	{
		memset(suma, 0, sizeof suma);
		memset(sumb, 0, sizeof sumb);
		int n, m;
		ll sum = 0;
		cin >> n >> m;
		_for(i, 0, n) cin >> a[i], sum += a[i];
		vi cnta, cntb;
		_for(i, 0, n)
		{
			int x; cin >> x;
			if (x == 1) cnta.push_back(a[i]);
			else cntb.push_back(a[i]);
		}

		if (sum < m)
		{
			cout << -1 << endl;
			continue;
		}

		sort(cnta.begin(), cnta.end(), greater<int>());
		sort(cntb.begin(), cntb.end(), greater<int>());
		int sza = cnta.size(), szb = cntb.size();
		_for(i, 0, sza) suma[i + 1] = suma[i] + cnta[i];
		_for(i, 0, szb) sumb[i + 1] = sumb[i] + cntb[i];

		int ans = INF;
		_rep(i, 0, sza)
		{
			if (suma[i] >= m)
			{
				ans = min(ans, i);
				break;
			}
			
			int l = 1, r = szb;
			while (l < r)
			{
				int mid = l + r >> 1;
				if (sumb[mid] >= m - suma[i]) r = mid;
				else l = mid + 1;
			}
			if (l == r && sumb[l] >= m - suma[i]) ans = min(ans, i + l * 2);
		}
		cout << ans<< endl;
	}
	
	return 0;
}

E - Advertising Agency

大的全取,剩下的在相同数字中组合选取即可。

#include<bits/stdc++.h>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= (b); --i)
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> IntVec;

const int N = 1000 + 10, mod = 1e9 + 7;
int a[N];
ll infact[N], fact[N];

struct cmp
{
	bool operator () (const int& a, const int& b) const
	{
		return a > b;
	}
};

ll qmi(ll a, int k)
{
	ll res = 1;
	while (k)
	{
		if (k & 1) res = res * a % mod;
		a = a * a % mod;
		k >>= 1;
	}
	return res;
}

void init()
{
	fact[0] = infact[0] = 1;
	_for(i, 1, N) fact[i] = fact[i - 1] * i % mod;
	infact[N - 1] = qmi(fact[N - 1], mod - 2);
	FOR(i, N - 2, 1) infact[i] = infact[i + 1] * (i * 1ll + 1) % mod;
}

int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin.tie(0);

	init();
	int T;
	cin >> T;
	while (T--)
	{
		int n, k;
		cin >> n >> k;
		_for(i, 0, n) cin >> a[i];
		sort(a, a + n, cmp());

		int c = 0;
		for (int i = k - 1; i >= 0 && a[k - 1] == a[i]; --i) c++;
		int d = c;
		for (int i = k; i < n && a[i] == a[k - 1]; ++i) d++;
		cout << fact[d] * infact[c] % mod * infact[d - c] % mod << endl;
	}
	return 0;
}

F - Unusual Matrix

贪心思想,定一变一。
如果某行或者某列的第一个是不一样的, 那么他这一行或者列就要进行异或操作。

#include<bits/stdc++.h>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= (b); --i)

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 1000 + 10, INF = 0x3f3f3f3f;
int n, a[N][N], b[N][N], c[N][N];
char s[N];

bool check()
{
	memcpy(c, a, sizeof a);
	_for(j, 0, n) if (c[0][j] != b[0][j]) _for(i, 0, n) c[i][j] ^= 1;
	_for (i, 0, n)
	{
		bool st = c[i][0] ^ b[i][0];
		_for(j, 1, n) if ((c[i][j] ^ b[i][j]) != st) return false;
	}
	return true;
}

inline void slove()
{
	_for (t, 0, 2)
	{
		if(check())
		{
			puts("YES");
			return;
		}
		_for(j, 0, n) a[0][j] ^= 1;
	}
	puts("NO");
}

int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	int T;
	cin >> T;
	while (T--)
	{
		cin >> n;
		_for(i, 0, n) {
			cin >> s;
			_for(j, 0, n) a[i][j] = s[j] - '0';
		}
		
		_for(i, 0, n)
		{
			cin >> s;
			_for(j, 0, n) b[i][j] = s[j] - '0';
		}

		slove();
	} 
	
	return 0;
}

G - Strange Beauty

dp + 数论
情况不定,找不到贪心方法又要求最优解, 所以就想到了DP,往DP方向想, 首先得确定他是几维的, 限制条件只有一个, 就是两两相互成倍数关系,所以确定为一维状态。
那么就表示为在前i个数中, 成倍数关系的数字有多少个。

#include<bits/stdc++.h>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= (b); --i)

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 200000 + 10;
int dp[N], cnt[N];

int main()
{
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	int T;
	cin >> T;
	while (T--)
	{
		memset(dp, 0, sizeof dp);
		memset(cnt, 0, sizeof cnt);
		int n;
		cin >> n;
		_for(i, 0, n)
		{
			int x; cin >> x;
			cnt[x]++;
		}

		_for(i, 1, N)
		{
			dp[i] += cnt[i];
			for (int j = i * 2; j < N; j += i) dp[j] = max(dp[j], dp[i]);
		}

		cout << n - *(max_element(dp, dp + N)) << endl;
	} 
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值