题目来源
【比赛】 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;
}