Topic link: abc190
A - Very Very Primitive Game
Topic
- Takahashi and Aoki eat sweets, take turns eating sweets, and lose if the person in turn has no sweets.
- a is the number of candies owned by T, b is the number of candies owned by A, c=0 means T eats first, c=1 means A eats first.
- Output winner
- 0≤A,B≤100
Ideas
- A to eat first means that T has eaten one, so you can let a+c, then unified T will eat candy first
- If a>b then T wins, otherwise A wins
ac code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
int a, b, c;
cin >> a >> b >> c;
a += c;
if(a > b) puts("Takahashi");
else puts("Aoki");
return 0;
}
B - Magic 3
Topic
- Magician fight monsters, n kinds of spells, each spell duration is ai, damage is bi
- The shortest time a monster can withstand is s and the maximum damage is d
- Ask the magician to successfully kill the monster
- Range 1≤N≤100, 1≤ai≤1e9, 1≤bi≤1e9, 1≤s≤1e9, 1≤d≤1e9
Ideas
- Find if there is ai<s and bi>d in all the spells
- And operation is used here
ac code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
int n, s, d, flag = 0;
scanf("%d%d%d", &n, &s, &d);
while(n --){
int x, y;
scanf("%d%d", &x, &y);
flag |= (x < s && y > d);
}
if(flag) puts("Yes");
else puts("No");
return 0;
}
C - Bowls and Dishes
Topic
- There are n kinds of dishes, m kinds of collocation a1, bi, k individual choice dishes,
- Everyone has two choices: ci and di. After choosing, see how many collocations are satisfied
- Ask how many matches are met at most
- Range: 2≤N≤100, 1≤M≤100, 1≤Ai<Bi≤N, 1≤K≤16, 1≤Ci<Di≤N
Ideas
- State compression
- Because there are only 16 people at most, you can enumerate all situations in binary, 0 means choose the first dish, 1 means choose the second dish, and mark the vis array
- Then traverse the collocation, if both exist, then cnt++, and finally update the maximum value of cnt
ac code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[105], b[105], c[105], d[105];
int vis[105];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i ++){
scanf("%d%d", &a[i], &b[i]);
}
int k; scanf("%d", &k);
for(int i = 0; i < k; i ++){
scanf("%d%d", &c[i], &d[i]);
}
int ans = 0;
for(int t = 0; t < (1 << k); t ++){
for(int i = 1; i <= n; i ++) vis[i] = 0;
for(int i = 0; i < k; i ++){
if((t >> i) & 1) vis[d[i]] = 1;
else vis[c[i]] = 1;
}
int cnt = 0;
for(int i = 1; i <= m; i ++){
if(vis[a[i]] + vis[b[i]] == 2) cnt ++;
}
ans = max(ans, cnt);
}
printf("%d\n", ans);
return 0;
}
D - Staircase Sequences
Topic
- Give you an n, and ask you how many arithmetic series can be formed, the tolerance d is 1, and the sum of the series is n?
- 1≤N≤1e12
Ideas
- The sum formula of the arithmetic sequence is S=n*a0+n*(n-1)*d/2
- d=1, then S is related to the number of terms n and the first term a0, S is known, then use n to represent a0: a0=S/n-(n-1)/2 -> 2a0=2S/n+ 1-n
- a0 is an integer, so 2S/n+1-n is an even number, and n is a factor of 2S.
- Run O(
) time to find the number of n that satisfy the condition.
ac code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
ll n; cin >> n;
int cnt = 0;
n <<= 1;
for(int i = 1; i <= sqrt(n); i ++){
if(n % i == 0){
if((n / i + 1 - i) % 2 == 0) cnt ++;
ll d = n / i;
if(i == d) continue;
if((n / d + 1 - d) % 2 == 0) cnt ++;
}
}
cout << cnt << endl;
return 0;
}
F - Shift and Inversions
Topic
- Give you n arrays from 0 to n-1, and then this array will rotate to the left by n-1
- Ask you what is the reverse number pair of the array in this process
- Inverse number pairs, the number of pairs <i, j> satisfying i<j, ai>aj
- 2≤N≤3×1e5
Ideas
- The initial reverse order of ans is done with a tree array or merge sort, here is a tree array,
- Then, for example, {2, 0, 1, 3} this pair of circular shifts to the left becomes {0, 1, 3, 2}, that is, 2 is moved backward, then now, the number smaller than 2 is moved to the left, reverse order There are fewer pairs of a1, and numbers larger than 2 are also moved to the left, and there are more pairs of a2 in reverse order.
- Since it is a full permutation, then the number a1 smaller than 2 has 2 pairs, and the number larger than 2 a2 has 4-1-2 pairs, which means that only ans-a1 + a2 is needed.
- The maximum value of the reverse order pair is n*(n-1) / 2 so it will explode int, and long long needs to be opened
ac code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) x & -x
const int maxn = 3e5 + 5;
int c[maxn], n;
void add(int x){
for(int i = x; i <= n; i += lowbit(i))
c[i] ++;
}
int query(int x){
int ans = 0;
for(int i = x; i > 0; i -= lowbit(i))
ans += c[i];
return ans;
}
int a[maxn];
int main(){
ll ans = 0; cin >> n;
for(int i = 1; i <= n; i ++){
cin >> a[i]; a[i] ++;
//由于树状数组不能加0,所以a[i]需要加1,那么下面的d1就要对应的+1, d2要对应的-1
add(a[i]);
//query求的是小于等于a[i]的数的个数,i是现在有的个数
//那么现在要求的是逆序对,也就是要求前面比他大的数的个数,那么就是i-query
ans += i - query(a[i]);
}
int d1 = 0, d2 = 0;
for(int i = 1; i <= n; i ++){
cout << ans << endl;
d1 = n - a[i], d2 = a[i] - 1;
ans += d1 - d2;
}
return 0;
}