文章目录
2020牛客暑期多校训练营(第四场)题解及补题
比赛过程
一共出了三题。依次为BFH,这次吸取教训,前期求稳了,也得到了稳的好处,罚时相对低了。
题解
A
题意
解法
代码
B
题意
给出定义 f c ( x ) = max 1 < i < x − 1 c ⋅ f c ( g c d ( i , x ) ) , x > 1 ; f c ( x ) = 1 , x = 1 f_c(x)=\max\limits_{1< i < x-1} c\cdot f_c(gcd(i,x)),x>1;f_c(x)=1,x=1 fc(x)=1<i<x−1maxc⋅fc(gcd(i,x)),x>1;fc(x)=1,x=1。问给定的n,c下最大的 f c ( n ) f_c(n) fc(n)
解法
容易发现,最后答案即为 c i c^i ci的形式,容易证明i的最大值即质因子的指数和。
代码
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
const ll maxn = 1e6 + 111;
const ll mod = 1e9 + 7;
ll v[maxn] = {0}, prime[maxn], m = 0; // v为最小质因子 v==i则为质数 1看情况取
void primes(ll n) {
for (ll i = 2; i <= n; ++i) {
if (!v[i]) { // i为质数
v[i] = i;
prime[++m] = i;
}
//给当前的数i乘上一个质因子
for (ll j = 1; j <= m; ++j) {
// i有比prime[j]更小的质因子,或者超出n的范围
if (prime[j] > v[i] || prime[j] * i > n) break;
// prime[j]是合数i*prime[j]的最小质因子
v[i * prime[j]] = prime[j];
}
}
}
ll qm(ll a, ll b, ll mod) {
ll ret = 1, cnt = a;
while (b) {
if (b & 1) {
ret = ret * cnt % mod;
}
cnt = cnt * cnt % mod;
b >>= 1;
}
return ret;
}
int main() {
v[1] = 1;
primes(1000000);
ll T;
scanf("%lld", &T);
while (T--) {
ll n, c;
scanf("%lld%lld", &n, &c);
ll cnt = 0;
while (n != 1) {
n /= v[n];
++cnt;
}
printf("%lld\n", qm(c, cnt, mod));
}
return 0;
}
C
题意
解法
代码
D
题意
解法
代码
E
题意
解法
代码
F
题意
两条平行线AB,CD。给出长度AC,AD,BC,BD,问以AB为参照下,C在D前还是后。
解法
分类讨论,总共分成四种情况,分别算出这些情况下的长度相对关系,然后由对称性质可证其正确性。
代码
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
const ll maxn = 1e6 + 111;
const ll mod = 1e9 + 7;
int main() {
ll T;
scanf("%lld", &T);
while (T--) {
ll ac, ad, bc, bd;
cin >> ac >> ad >> bc >> bd;
int flag = 0;
if (ac > ad && bc > bd && ac < bc && ad < bd) {
flag = 1;
} else if (ac < ad && bc < bd && ac > bc && ad > bd) {
flag = 1;
} else if (ac <= ad && bc >= bd) {
flag = 1;
} else if (ac <= bc && ad >= bd) {
flag = 1;
} else {
}
if (flag) {
puts("AB//CD");
} else {
puts("AB//DC");
}
}
return 0;
}
G
题意
解法
代码
H
题意
给出一个整数n,问1到n的点最多多少个非互质点对。
解法
以因子中最小质数为标识区分这些数,然后从大到小遍历,如果数量为偶数,内部匹配,否则,从2中拉来一个凑数。
代码
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
const ll maxn = 1e6 + 111;
const ll mod = 1e9 + 7;
ll v[maxn] = {0}, prime[maxn], m = 0; // v为最小质因子 v==i则为质数 1看情况取
void primes(ll n) {
for (ll i = 2; i <= n; ++i) {
if (!v[i]) { // i为质数
v[i] = i;
prime[++m] = i;
}
//给当前的数i乘上一个质因子
for (ll j = 1; j <= m; ++j) {
// i有比prime[j]更小的质因子,或者超出n的范围
if (prime[j] > v[i] || prime[j] * i > n) break;
// prime[j]是合数i*prime[j]的最小质因子
v[i * prime[j]] = prime[j];
}
}
}
vector<ll> fac[200000];
ll flag[maxn];
int main() {
ll T;
primes(200000);
scanf("%lld", &T);
while (T--) {
ll n;
scanf("%lld", &n);
vector<ll> vec;
for (ll i = 1; i <= n; ++i) {
flag[i] = 0;
fac[i].clear();
}
for (ll i = 2; i <= n; ++i) {
if (v[i] == i) {
if (i * 2 > n) break;
vec.push_back(i);
fac[i].push_back(i);
ll cnt = i;
ll add = 1;
if (i > 2) add = 2;
while (cnt * i <= n) {
if (v[cnt] < i) {
cnt += add;
continue;
}
fac[i].push_back(cnt * i);
cnt += add;
}
}
}
reverse(vec.begin(), vec.end());
ll numm = 0;
for (auto w : vec) {
numm += fac[w].size();
}
printf("%lld\n", numm / 2);
for (auto w : vec) {
if (w == 2) {
ll cnt = 0;
ll ans[2];
for (auto ww : fac[2]) {
if (flag[ww]) continue;
ans[cnt++] = ww;
if (cnt == 2) {
printf("%lld %lld\n", ans[0], ans[1]);
cnt = 0;
}
}
} else {
ll i = 0;
if (fac[w].size() & 1) {
flag[2 * w] = 1;
printf("%lld %lld\n", w, 2 * w);
i = 1;
}
ll rr = fac[w].size();
for (; i < rr; i += 2) {
printf("%lld %lld\n", fac[w][i], fac[w][i + 1]);
}
}
}
}
return 0;
}
I
题意
解法
代码
J
题意
解法
代码
K
题意
解法
代码