Codeforces Round #665 Div.2 (CF1401)
A:
在一维坐标的\(OX\)象限中,给定\(A,k\),可以让\(A\)左移或右移1个单位任意次,求能找到点\(B\)、使得\(|OB-AB|=k\)的最小移动次数。
当\(A < k\)时,需要将\(A\)移至\(k\),此时\(B=0\)或\(B=k\),所以答案为\(k-n\)。
当\(A >= k\)时,化简\(|OB-AB|=k\)得\((A-B)-(B-O)=k\),即\(B=(A-k)/2\),当\(A, k\)奇偶性不同时,\(B\)为小数,这是需要把\(A\)右移一单位,答案为\(1\),否则答案为\(0\)。
Code:
/*
ID: Loxilante
Time: 2020/08/21
Prog: CF1401A
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\\Users\\Joeon\\Desktop\\IN.txt", "r", stdin);
// freopen("C:\\Users\\Joeon\\Desktop\\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next();
clock_t InputFinished = clock();
while(T--)
{
int n, k;
cin>>n>>k;
if (k > n) cout<<k-n<<endl;
else cout<<(n%2 != k%2)<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
B:
给你两个长度相等的数列\(a, b\),数列元素顺序可以随意调换,\(a\)数列有且仅有\(a0, a1, a1\)个\(0, 1, 2\),\(b\)数列有且仅有\(b0, b1, b2\)个\(0, 1, 2\)。现有一个\(c\)序列,\(c_i=\)
- \(a_i*b_i (a_i > b_i)\)
- \(0 (a_i = b_i)\)
- \(-a_i*b_i (a_i < b_i)\)
求最大的$ \sum _{i=1} ^{n} c_i$。
这是一个明显的贪心题,把\(b2\)用\(a0\)和\(a2\)抵消,如果剩下\(a2\)就输出\(min\{a2, b1\}\),如果剩下\(b2\)就输出\(-2*b2\)。
Code:
/*
ID: Loxilante
Time: 2020/08/14
Prog: CF1401B
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\\Users\\Joeon\\Desktop\\IN.txt", "r", stdin);
// freopen("C:\\Users\\Joeon\\Desktop\\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next<int>();
clock_t InputFinished = clock();
while(T--)
{
int a0, a1, a2, b0, b1, b2;
cin>>a0>>a1>>a2>>b0>>b1>>b2;
if (a0 > b2) a0 -= b2, b2 = 0;
else b2 -= a0, a0 = 0;
if (b2)
{
if (a2 > b2) a2 -= b2, b2 = 0;
else b2 -= a2, a2 = 0;
}
if (a2) cout<<min(a2, b1)*2<<endl;
else cout<<-2*b2<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
C:
给你一个序列\(a\),其中最小的元素的值为\(a_min\),若\(gcd(a_i, a_j) = a_{min}\),则可交换\(a_i, a_j\)。
把序列\(a\)先排好序变成序列\(b\),如果\(a_i ≡ b_i (mod a_{min})\),则可以交换,否则输出NO。
Code:
/*
ID: Loxilante
Time: 2020/08/21
Prog: CF1401C
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
const int U = 1e6;
int w[U], p[U];
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\\Users\\Joeon\\Desktop\\IN.txt", "r", stdin);
// freopen("C:\\Users\\Joeon\\Desktop\\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next();
clock_t InputFinished = clock();
while(T--)
{
int l = next();
bool yes = 1;
rep(i, 0, l) cin>>w[i], p[i] = w[i];
rep(i, 1, l) if (w[i] < w[i-1]) {yes = 0; break;}
if (yes) { cout<<"YES"<<endl; continue; }
sort(p, p+l);
int minn = p[0], no = 0, t;
rep(i, 0, l)
{
t = __gcd(p[i], w[i]);
if (t == p[i]) continue;
if (t % minn != 0) { no = 1; break; }
}
if (no) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
D:
一道1800的GOT题,思维难度中等,现场是没时间A
给定一个树,节点有\(n\)个,和一个数\(k\),要求给树的每一条边加边权,使得所有边权的乘积等于\(k\)。
由于\(k\)很大,所以题目会给你一个长为\(m\)的序列\(w\),其中每一个元素都是素数,并且\(k = \prod _{i = 1} ^{m} w_i\)。
边权为\(1\)的边要尽可能少。
现有函数\(f(u, v)\),表示从\(u\)到\(v\)的边权总和,求$ \sum _{i = 1} ^n \sum _{j = i+1} ^n f(i, j)$最大值。
考虑 Greedy ,我们用dfs求出 $ \sum _{i = 1} ^n \sum _{j = i+1} ^n f(i, j)$ 中每条边经过的次数,然后与 \(w\) 中元素大乘大,小乘小,加起来就是答案。
细下来考虑,不难发现可以分为两种情况:
- \(n-1 > m\),序列\(w\)中的数配对边权是不够用的,这时我们给剩下的边权画\(1\)。
- \(n-1 <= m\),序列\(w\)中的数不仅能够配对,还能多余。这时我们要再考虑有两种方案,一是把\(w\)中小的数乘上大的,二是把\(w\)中大的数乘上大的,显然,随便造组数据就能把一hack掉,
然而我还是写了一然后义无反顾的WA on test 2。
思路大体讲完了,还要考虑一些小细节
- 数组清零(
废话) - 把\(w\)中的大数乘上大数时要记得取模,不然要爆long long。
Code:
/*
ID: Loxilante
Time: 2020/08/28
Prog: CF1401D
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
const int U = 1e6+50;
const int mod = 1e9+7;
vector<int> edge[U], prime, passtimes;
int passed[U], n;
inline void dfs(int e, int father)
{
passed[e] = 1;
rep(i, 0, edge[e].size())
{
int to = edge[e][i];
if (to == father) continue;
dfs(to, e);
passed[e] += passed[to];
}
if (e != 1) passtimes.pb(passed[e]*(n-passed[e]));
}
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\\Users\\Joeon\\Desktop\\IN.txt", "r", stdin);
// freopen("C:\\Users\\Joeon\\Desktop\\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next();
clock_t InputFinished = clock();
while(T--)
{
int ans = 0;
cin>>n;
hrp(i, 0, n) edge[i].clear();
prime.clear();
passtimes.clear();
rep(i, 0, n-1)
{
int from, to;
cin>>from>>to;
edge[from].pb(to);
edge[to].pb(from);
}
dfs(1, 0);
sort(passtimes.begin(), passtimes.end(), greater<int>());
int m = next();
rep(i, 0, m) prime.pb(next());
sort(prime.begin(), prime.end(), greater<int>());
while(prime.size() >= n)
{
int t = prime.front();
prime.erase(prime.begin());
*prime.begin() *= t;
*prime.begin() %= mod;
}
rep(i, 0, passtimes.size())
ans = (ans+passtimes[i] * (i >= prime.size() ? 1 : prime[i]))%mod;
cout<<ans<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}