0%

nowcoder多校(第四场)

A.

题目描述:

题解:

代码:

1
2


B. Basic Gcd Problem

题目描述:

给出一个函数

给出一些 $ (n_i, c_i) $ ,求 $ f_{c_i}(n_i) mod(1e9+7) $

数据范围:
$ T(1≤T≤1e6) $ $ 1\le n_i,c_i \le 10^6 $

题解:

观察可以发现, $ f_c(x) = c^{x质因子个数} $

数据比较大,使用筛一下,求解即可

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const ll mod = 1e9 + 7;


int t;
ll n, c, d;

ll qpow(ll a, ll b, ll mod)
{
ll ans = 1, tmp = a;
while(b)
{
if(b & 1) ans = ans * tmp % mod;
tmp = tmp * tmp % mod;
b >>= 1;
}
return ans % mod;
}

int prime[maxn];
bool notPrime[maxn];
int cnt = 0, num[maxn];
int from[maxn]; // 用来记录每个数的最小质因子
void sieve(int n)
{
for(int i = 2; i <= n; i++)
{
if(!notPrime[i])
{
prime[++cnt] = from[i] = i;
num[i] = 1; // 修改一下筛法,加上递推
}
for(int j = 1; prime[j] * i <= n && j <= cnt; j++)
{
from[i * prime[j]] = prime[j];
num[i * prime[j]] = num[i] + 1; // 修改一下筛法,加上递推
notPrime[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%d", &t);
sieve(1e6 + 3);
while(t--)
{
scanf("%lld%lld", &n, &c);
printf("%lld\n", qpow(c, num[n], mod));
}
return 0;
}

C.

题目描述:

题解:

代码:

1
2


D. Dividing Strings

题目描述:

给出一个数字字符串,要求分割为若干段,使得最大值和最小值的差尽量小

数据范围

$ 2 \le n \le 10^5,’0’ \le s[i] \le ‘9’,\sum{n}\le 10^6 $

题解:

显然,答案 $ \le 9 $ ,每一段都是一位数

下面分两种情况继续讨论:

  • 划分的每一段长度都相等(枚举约数,线性扫一遍)
  • 最大段和最小段长度相差 $ 1 $ ,形式只能是 $ 99\cdots9x $ 和 $ 100\cdots y $ , $ x = 2\cdots9,y=0\cdots7 $ 是对应的。因为 $ x $ 不能是 $ 1 $ $ y $ 不能是 $ 9 $ ,容易发现,满足这种构型的
    方案只有 $ O(1) $ 种,稍微特判一下即可。复杂度 $ 𝑶(𝑁) $

代码:

1
2


E.

题目描述:

题解:

代码:

1
2


F. Finding the Order

题目描述:

两条线 $ AB,CD $ ,输入距离 $ AC,AD,BC,BD $ ,判断是下面那种情况

img

题解:

有很多种做法

  • 可以找到最大值,如果最大值来自 AD 或 BC ,则 $ AB//CD $ ,否则 $ AB//DC $ 。
  • image-20200722211309364也可以像这样,得到两个三角形,判断一下两边和大于第三边, $ AC+BD $ 和 $ AD+BC $

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
const LL MOD = 1e9 + 9;
int t;
int a, b, c, d;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%d", &t);
while(t--)
{
scanf("%d%d%d%d", &a,&b,&c,&d);
cout << ((a+d < b+c) ? "AB//CD" : "AB//DC") << endl;
}
return 0;
}

G.

题目描述:

题解:

代码:

1
2


H. Harder Gcd Problem

题目描述:

$ B $ 题的 $ hard $ 版本,给出 $ 1-n $ 的一个序列,求出两个长度最大为 $ m $ 的子集 $ A,B $ ,对应的元素有 $ gcd(a_i, b_i)>1 $

数据范围:
$ 4\le n \le 2\times10^5,\sum{n} \le 2 \times 10^5 $

题解:

构造,方法是

$ p\times2>n $ 的 $ p $ 必然不能匹配,将它们除去。
倒序枚举所有质因子 $ p $ ,考虑所有是 $ p $ 的倍数、且未被匹
配的数,任意将它们进行匹配。
如果个数是奇数就留下 $ p\times2 $ 。
最后把剩下的偶数都随意匹配一下。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const ll mod = 1e9 + 7;

int t;
ll n, c, d;
vector<pair<ll, ll> > ans;
ll a[maxn];
ll prime[maxn];
bool notPrime[maxn];
ll cnt = 0;
ll from[maxn]; // 用来记录每个数的最小质因子
void sieve(ll n)
{
for(ll i = 2; i <= n; i++)
{
if(!notPrime[i]) prime[++cnt] = from[i] = i;
for(ll j = 1; prime[j] * i <= n && j <= cnt; j++)
{
from[i * prime[j]] = prime[j];
notPrime[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
scanf("%d", &t);
sieve(2e5 + 3);
while(t--)
{
scanf("%d", &n);
ans.clear();
memset(a, 0, sizeof(a));
ll p = 0;
for(ll i = 1; i <= cnt; i++)
{
if(prime[i] > n) break;
if(prime[i] > (n >> 1)) a[prime[i]] = -1, p = i;
}
int tmp, k = 0;
for(ll i = p; i >= 1; i--)
{
if(a[prime[i]] == -1) continue;
k = 0;
for(ll j = 1; j * prime[i] <= n; j++)
{
if(a[j * prime[i]] == -1 || j == 2) continue;
k++;
if(k&1) tmp = j * prime[i];
else
{
ans.push_back({tmp, j * prime[i]});
k = 0;
a[tmp] = a[j * prime[i]] = -1;
}
}
if(k == 1)
{
ans.push_back({tmp, 2 * prime[i]});
a[tmp] = a[2 * prime[i]] = -1;
}
}

k = 0;
for(ll i = 1; i <= n; i++)
{
if((i%2==0) && a[i] != -1)
{
k++;
if(k & 1) tmp = i;
else
{
ans.push_back({tmp, i});
k = 0;
}
}
}
printf("%d\n", ans.size());
for(auto x : ans)
{
printf("%lld %lld\n", x.first, x.second);
}
}
return 0;
}

I.

题目描述:

题解:

代码:

1
2