AtCoder Beginner Contest 152
Posted Zeoy-kkk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 152相关的知识,希望对你有一定的参考价值。
Flatten
给定\\(n\\)个正整数\\(a_i\\),,现在让你求出\\(n\\)个整数\\(b_i\\),使得任取\\(1\\le i < j \\le n\\),\\(a_ib_i=a_jb_j\\)始终成立,请你求出\\(\\sum b_i\\)的最小值,答案对\\(1e9+7\\)取模
\\(1\\le n \\le 10^4\\)
\\(1 \\le a_i \\le 10^6\\)
题解:最大公倍数取模 + 质因数分解 + 快速幂求乘法逆元
- 容易得到\\(a_ib_i = lcm(\\sum a_i)\\),那么我们现在只要求出\\(n\\)个\\(a_i\\)的最大公倍数\\(lcm\\)且对\\(1e9+7\\)取模的结果,答案即为
\\[\\sum_i=1^n\\fraclcma_i \\]
- 答案中存在除法,但是取模中没有除法,所以我们需要利用快速幂求出\\(a_i\\)在模\\(1e9+7\\)下的乘法逆元\\(a_i^-1\\),答案为
\\[\\sum_i=1^nlcm*a_i^-1 \\]
- 现在我们还需要解决最大公倍数取模的问题:
我们对每个\\(a_i\\)进行质因子分解,取每个质因子中的最大幂次作为最大公倍数的对应质因子的幂次,然后利用快速幂求出最大公倍数对\\(1e9+7\\)取模的结果
- 时间复杂度:质因子分解\\(O(\\sqrt a_i)\\),一共\\(n\\)个数,\\(O(n\\sqrt a_i)\\),最终时间复杂度为\\(O(n\\sqrt a_i + nlog(1e9))\\)
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << \'=\' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl \'\\n\'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e6 + 10, M = 4e5 + 10;
int n;
int a[N];
int p[N], idx;
bool vis[N];
unordered_map<int, int> mp2;
int qpow(int a, int b, int p)
int res = 1;
while (b)
if (b & 1)
res = res * a % p;
a = a * a % p;
b >>= 1;
return res % p;
void solve()
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
int t = a[i];
unordered_map<int, int> mp;
for (int j = 2; j <= t / j; ++j)
while (t % j == 0)
mp[j]++;
mp2[j] = max(mp2[j], mp[j]);
t /= j;
if (t > 1)
mp[t]++;
mp2[t] = max(mp2[t], mp[t]);
int d = 1;
for (auto [x, y] : mp2)
d = d * qpow(x, y, mod) % mod;
int ans = 0;
for (int i = 1; i <= n; ++i)
ans = (ans % mod + (d % mod * qpow(a[i], mod - 2, mod)) % mod) % mod;
cout << ans << endl;
signed main(void)
Zeoy;
int T = 1;
// cin >> T;
while (T--)
solve();
return 0;
Tree and Constraints
给你一颗有\\(n\\)个节点的树,你要给这棵树黑白染色,并且符合\\(m\\)条限制,每条限制给定\\(u\\)和\\(v\\),需要满足\\(u\\)到\\(v\\)的路径上至少有一个黑色边,问有多少种染色方案
\\(2≤n≤50\\)
\\(1≤m≤min(20,2n(n−1))\\)
题解:容斥原理 + 状压 + 树上异或 \\(O(2^mm)\\)
- 首先染色总方案数\\(S\\)为\\(2^n-1\\),设\\(A_i\\)为满足第\\(i\\)个限制条件的合法方案数,题目想让我们求出\\(\\bigcap_i=1^mA_i\\),即所有限制条件合法方案数的交集,但是比较难求,正难则反,我们不妨从反面考虑该答案:
设\\(\\barA_i\\)为不满足第\\(i\\)个限制条件的不合法方案数,那么我们把题目想让我们求的答案可以转化为
\\[S-\\bigcup_i-1^m\\barA_i \\]因为\\(m\\le 20\\),容易发现我们可以利用容斥原理求出\\(\\bigcup_i-1^m\\barA_i\\) ,时间复杂度为:\\(O(2^mm)\\)
- 那么现在我们要做的就是求出\\(\\barA_i\\),那么我们分析一下:
对于不满足\\(u\\)和\\(v\\)的限制条件的方案数\\(\\barA_i\\),只要\\(u\\)和\\(v\\)之间的所有边都涂成白色,那么其他不在\\(u\\)和\\(v\\)之间的边,颜色就可以随便涂,设\\(u\\)和\\(v\\)之间的边数为\\(cnt\\),那么
\\[\\barA_i = 2^n-1-cnt \\]
- 我们已经知道了\\(\\barA_i\\)怎么求,只要知道\\(u\\)和\\(v\\)之间的边数即可,但是我们在进行容斥的时候我们需要求出多个不合法方案之间的交集,那么交集就意味着我们涂的方案需要使得多个限制条件同时无法满足,即我们需要将所有限制条件里的边都涂成白色,所以说我们需要知道多个限制条件中边的并集,也就是说我们需要知道每个限制条件\\(u\\)和\\(v\\)之间的边具体有哪些边,我们考虑如何解决这个问题:
因为\\(n \\le 50\\),所以我们不妨将每个点到根节点的路径中边的状态利用二进制压缩,我们设点\\(u\\)到根节点的路径中边的状态为\\(path_u\\),我们设第\\(i\\)个限制条件\\((u,v)\\)之间边的信息为\\(info_i\\),利用树上异或的性质:\\[info_i = path_u \\bigoplus path_v \\]我们可以求出\\(u\\)和\\(v\\)之间有哪些边存在
- 对于多个限制条件中边的并集的状态\\(num\\)为
\\[\\sum num\\ \\ |= \\ \\ info_i \\]
- 设状态\\(num\\)中\\(1\\)的数量为\\(cnt\\)(即边的数量),那么对于不满足多个限制条件的方案的交集为
\\[2^n-1-cnt \\]
- 最后利用容斥原理解题即可
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << \'=\' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl \'\\n\'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 50 + 10, M = 4e5 + 10;
int n, m;
vector<int> g[N];
int path[N];
int info[N];
void dfs(int u, int par)
path[u] = path[par] | (1ll << u);
for (auto v : g[u])
if (v == par)
continue;
dfs(v, u);
void solve()
cin >> n;
for (int i = 1, u, v; i < n; ++i)
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
dfs(1, 0);
cin >> m;
for (int i = 0, u, v; i < m; ++i)
cin >> u >> v;
info[i] = path[u] ^ path[v];
int ans = 0;
for (int i = 1; i < (1 << m); ++i)
int cnt = 0;
int num = 0;
for (int j = 0; j < m; ++j)
if (i >> j & 1)
cnt++;
num |= info[j];
int free = n - 1 - __builtin_popcountll(num);
if (cnt % 2 == 1)
ans += (1ll << free);
else
ans -= (1ll << free);
cout << (1ll << (n - 1)) - ans << endl;
signed main(void)
Zeoy;
int T = 1;
// cin >> T;
while (T--)
solve();
return 0;
AtCoder Beginner Contest 115 题解
题目链接:https://abc115.contest.atcoder.jp/
A Christmas Eve Eve Eve
题目:
Time limit : 2sec / Memory limit : 1024MB
Score : 100 points
Problem Statement
In some other world, today is December D-th.
Write a program that prints Christmas if D=25, Christmas Eve if D=24, Christmas Eve Eve if D=23 and Christmas Eve Eve Eve if D=22.
Constraints
- 22≤D≤25
- D is an integer.
Input
Input is given from Standard Input in the following format:
D
Output
Print the specified string (case-sensitive).
Sample Input 1
25
Sample Output 1
Christmas
Sample Input 2
22
Sample Output 2
Christmas Eve Eve Eve
Be sure to print spaces between the words.
题解:
没什么好说的。
1 #include <cstdio> 2 3 using namespace std; 4 5 int main() 6 { 7 int d; 8 scanf("%d", &d); 9 if(d == 25) 10 printf("Christmas "); 11 else if(d == 24) 12 printf("Christmas Eve "); 13 else if(d == 23) 14 printf("Christmas Eve Eve "); 15 else if(d == 22) 16 printf("Christmas Eve Eve Eve "); 17 return 0; 18 }
B Christmas Eve Eve
题目:
Time limit : 2sec / Memory limit : 1024MB
Score : 200 points
Problem Statement
In some other world, today is the day before Christmas Eve.
Mr. Takaha is buying N items at a department store. The regular price of the i-th item (1≤i≤N) is pi yen (the currency of Japan).
He has a discount coupon, and can buy one item with the highest price for half the regular price. The remaining N?1 items cost their regular prices. What is the total amount he will pay?
Constraints
- 2≤N≤10
- 100≤pi≤10000
- pi is an even number.
Input
Input is given from Standard Input in the following format:
N
p1
p2
:
pN
Output
Print the total amount Mr. Takaha will pay.
Sample Input 1
3
4980
7980
6980
Sample Output 1
15950
The 7980-yen item gets the discount and the total is 4980+7980?2+6980=15950 yen.
Note that outputs such as 15950.0 will be judged as Wrong Answer.
Sample Input 2
4
4320
4320
4320
4320
Sample Output 2
15120
Only one of the four items gets the discount and the total is 4320?2+4320+4320+4320=15120 yen.
题解:
没什么好说的。
1 #include <cstdio> 2 #include <iostream> 3 4 using namespace std; 5 6 int main() 7 { 8 int n; 9 scanf("%d", &n); 10 int p[15], maxp = 0, sum = 0; 11 for(int i = 0; i < n; ++i) 12 { 13 scanf("%d", &p[i]); 14 maxp = max(maxp, p[i]); 15 sum += p[i]; 16 } 17 sum = sum - maxp + maxp / 2; 18 printf("%d ", sum); 19 return 0; 20 }
C Christmas Eve
题目:
Time limit : 2sec / Memory limit : 1024MB
Score : 300 points
Problem Statement
In some other world, today is Christmas Eve.
There are N trees planted in Mr. Takaha‘s garden. The height of the i-th tree (1≤i≤N) is hi meters.
He decides to choose K trees from these trees and decorate them with electric lights. To make the scenery more beautiful, the heights of the decorated trees should be as close to each other as possible.
More specifically, let the height of the tallest decorated tree be hmax meters, and the height of the shortest decorated tree be hmin meters. The smaller the value hmax?hmin is, the better. What is the minimum possible value of hmax?hmin?
Constraints
- 2≤K<N≤105
- 1≤hi≤109
- hi is an integer.
Input
Input is given from Standard Input in the following format:
N K
h1
h2
:
hN
Output
Print the minimum possible value of hmax?hmin.
Sample Input 1
5 3
10
15
11
14
12
Sample Output 1
2
If we decorate the first, third and fifth trees, hmax=12,hmin=10 so hmax?hmin=2. This is optimal.
Sample Input 2
5 3
5
7
5
7
7
Sample Output 2
0
If we decorate the second, fourth and fifth trees, hmax=7,hmin=7 so hmax?hmin=0. This is optimal.
There are not too many trees in these sample inputs, but note that there can be at most one hundred thousand trees (we just can‘t put a sample with a hundred thousand lines here).
题解:
最终的答案就是k个数中的最大高度-最小高度。要让答案尽可能的小,就要让这两个值尽可能接近。很容易想到排序一下,然后枚举第i个和第i+k-1个之间的差值(0≤i≤n-k),取最小值即可。
1 #include <cstdio> 2 #include <algorithm> 3 4 using namespace std; 5 6 int main() 7 { 8 int n, k; 9 scanf("%d %d", &n, &k); 10 int h[100005]; 11 for(int i = 0; i < n; ++i) 12 scanf("%d", &h[i]); 13 sort(h, h + n); 14 int ans = 1e9; 15 for(int i = 0; i <= n - k; ++i) 16 ans = min(ans, h[i+k-1] - h[i]); 17 printf("%d ", ans); 18 return 0; 19 }
D Christmas
题目:
Time limit : 2sec / Memory limit : 1024MB
Score : 400 points
Problem Statement
In some other world, today is Christmas.
Mr. Takaha decides to make a multi-dimensional burger in his party. A level-L burger (L is an integer greater than or equal to 0) is the following thing:
- A level-0 burger is a patty.
- A level-L burger (L≥1) is a bun, a level-(L?1) burger, a patty, another level-(L?1) burger and another bun, stacked vertically in this order from the bottom.
For example, a level-1 burger and a level-2 burger look like BPPPB and BBPPPBPBPPPBB (rotated 90 degrees), where B and P stands for a bun and a patty.
The burger Mr. Takaha will make is a level-N burger. Lunlun the Dachshund will eat X layers from the bottom of this burger (a layer is a patty or a bun). How many patties will she eat?
Constraints
- 1≤N≤50
- 1≤X≤( the total number of layers in a level-N burger )
- N and X are integers.
Input
Input is given from Standard Input in the following format:
N X
Output
Print the number of patties in the bottom-most X layers from the bottom of a level-N burger.
Sample Input 1
2 7
Sample Output 1
4
There are 4 patties in the bottom-most 7 layers of a level-2 burger (BBPPPBPBPPPBB).
Sample Input 2
1 1
Sample Output 2
0
The bottom-most layer of a level-1 burger is a bun.
Sample Input 3
50 4321098765432109
Sample Output 3
2160549382716056
A level-50 burger is rather thick, to the extent that the number of its layers does not fit into a 32-bit integer.
题解:
题目中burger的定义是递归的定义,自然也想到用递归的方式去做。我们可以发现burger是对称的。那么就可以分段递归。nlen是每个burger的长度(高度),p记录的是每个burger含有的p的个数。这两个公式稍微推一下就可以得到,是一个等比数列的问题,这里不展开了。(事实上直接迭代也可以得到)
另外,我们可以发现X≤N的时候,ans=0;X≥nlen[N]的时候,ans=p[N]。由此可以写出代码。
注意输入输出的时候为了防止Compilation Error,用cin和cout较为妥当。
1 #include <cstdio> 2 #include <cmath> 3 #include <iostream> 4 5 using namespace std; 6 7 typedef unsigned long long ll; 8 9 ll p[55], nlen[55]; 10 11 ll solve(ll n, ll x) 12 { 13 if(x <= n) return 0; 14 if(x >= nlen[n] - 1) return p[n]; 15 if(x == nlen[n] / 2 + 1) return (p[n] / 2 + 1); 16 else if(x < nlen[n] / 2 + 1) 17 return solve(n - 1, x - 1); 18 else 19 return p[n] / 2 + 1 + solve(n - 1, x - nlen[n] / 2 - 1); 20 } 21 22 int main() 23 { 24 for(int i = 0; i <= 50; ++i) 25 { 26 p[i] = pow(2, i + 1) - 1; 27 nlen[i] = pow(2, i - 1) * 8 - 3; 28 } 29 ll n, x; 30 cin>>n>>x; 31 cout<<solve(n, x)<<endl; 32 return 0; 33 }
以上是关于AtCoder Beginner Contest 152的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解