比赛链接如下:AtCoder Beginner Contest 412 - AtCoder
5/7 讲解:
A - Task Failed Successfully
Problem Statement
Takahashi set task goals for N days.
He aimed to complete Ai tasks on day i(1≤i≤N)i(1≤i≤N), and actually completed Bi tasks.
Find the number of days when he completed more tasks than his goal.
Constraints
- 1≤N≤100
- 1≤Ai,Bi≤100
- All input values are integers.
解题思路:统计Bi大于Ai的数量
#include<bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
int cnt=0;
for(int i=0;i<n;i++){
int a,b; cin>>a>>b;
if(b>a) cnt++;
}
cout<<cnt<<endl;
return 0;
}
B - Precondition
Problem Statement
You are given strings S and TT consisting of lowercase and uppercase English letters.
Determine whether the string S satisfies the following condition:
- Every uppercase letter in S that is not at the beginning is immediately preceded by a character contained in T. More formally, for all integers ii such that 2≤i≤∣S∣, if the ii-th character of S is uppercase, then the (i−1)-th character of S is contained in T.
Constraints
- Each of S and TT is a string consisting of lowercase and uppercase English letters with length between 1 and 100, inclusive.
解题思路:顺次遍历字符串S,若当前字符S[i]是大写, 就查看S[i-1]是否在字符串T中
#include <bits/stdc++.h>
using namespace std;
int main() {
string s, t;
cin >> s >> t;
set<char> a;
for (char c : t) a.insert(c);
for (size_t i = 1; i < s.size(); i++) {
if (isupper(static_cast<unsigned char>(s[i]))) {
if (a.find(s[i - 1]) == a.end()) {
cout << "No" << endl;
return 0;
}
}
}
cout << "Yes" << endl;
return 0;
}
C - Giant Domino
Problem Statement
There are N dominoes numbered from 1 to N. The size of domino ii is Si.
Consider arranging some dominoes in a line from left to right and then toppling them. When domino i falls to the right, if the size of the domino placed immediately to the right of domino i is at most 2Si, then that domino also falls to the right.You decided to choose two or more dominoes and arrange them in a line from left to right. The arrangement of dominoes must satisfy the following conditions:
- The leftmost domino is domino 1.
- The rightmost domino is domino N
- When only domino 11 is toppled to the right, domino N eventually falls to the right as well.
Does an arrangement of dominoes satisfying the conditions exist? If it exists, what is the minimum number of dominoes that need to be arranged?
You are given T test cases, solve the problem for each of them.
Constraints
- 1≤T≤10^5
- 2≤N≤2×10^5
- 1≤Si≤10^9
- The sum of NN over all test cases is at most 2×10^5
- All input values are integers.
解题思路:
我们把每个多米诺i看作图中的一个节点,若S[j]<=2*S[i]则从i->j 有一条有向边
由于 N 最多 2*10^5,完全显式存边会爆炸,因此我们把所有未访问的节点放入一个set<pair<size,i>>
每次从队列中取出节点 u,计算 a = 2·S[u],在 set 里一次性"割去"所有 size≤a的节点v,标记它们距离并入队
最后看 dist[n],若仍是-1则不可达,输出-1,否则输出到达n的最小节点数.
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main(){
int t; cin>>t;
while(t--){
int n; cin>>n;
vector<ll> s(n+1);
for(int i=1;i<=n;i++) cin>>s[i];
vector<int> d(n+1,-1);
d[1]=1;
set<pair<ll,int>> st;
for(int i=2;i<=n;i++) st.insert({s[i],i});
queue<int> q;
q.push(1);
while(!q.empty()){
int u=q.front(); q.pop();
ll a=2LL*s[u];
auto b=st.upper_bound({a,INT_MAX});
for(auto x=st.begin();x!=b;){
int v=x->second;
d[v]=d[u]+1;
q.push(v);
x=st.erase(x);
}
}
cout<<d[n]<<endl;
}
return 0;
}
D - Make 2-Regular Graph
Problem Statement
There is a simple undirected graph G with N vertices and M edges. The vertices are numbered 1,2,…,N, and the ii-th edge is an undirected edge connecting vertices Ai and Bi.
You can repeat the following two operations in any order and any number of times:
- Add one undirected edge to G
- Remove one undirected edge from G
Find the minimum number of operations to make G a simple undirected graph where all vertices have degree 2.
解题思路:在当前图中添加一条边/删除一条边, 保证图中所有顶点度数均为2的最少操作次数
我们可以枚举:
所有 n! 的排列,代表顶点的遍历顺序。
对于每个排列,用 2^(n-1) 枚举所有「断环点」的位置,即在哪里断开形成多个环(每个环长度 ≥ 3)。
检查该划分是否合法(每个环长度 ≥ 3),并统计这些环中所有的边。
然后比较和原图重叠的边数,设有 cnt 条边在原图中,那么:
要删除 m - cnt 条多余边;
要添加 n - cnt 条缺失边;
总操作数为:(m - cnt) + (n - cnt) = m + n - 2 * cnt
我们要取最小操作数。
#include<bits/stdc++.h>
using namespace std;
using pii=pair<int,int>;
set<pii> g;
int n,m;
int solve(){
vector<int> p(n);
iota(p.begin(),p.end(),0);
int ans=INT_MAX;
do{
for(int m=0;m<(1<<(n-1));m++){
vector<vector<int>> c;
vector<int> cur;
bool f=true;
for(int i=0;i<n;i++){
cur.push_back(p[i]);
if(i==n-1||(m&(1<<i))){
if(cur.size()<3){
f=false;
break;
}
c.push_back(cur); cur.clear();
}
}
if(!f) continue;
set<pii> ne;
for(auto& x:c){
int n=x.size();
for(int i=0;i<n;i++){
int u=x[i],v=x[(i+1)%n];
if(u>v) swap(u,v);
ne.insert({u,v});
}
}
int cnt=0;
for(auto& [u,v]:ne){
if(g.count({u,v})) cnt++;
}
int ct=g.size()+ne.size()-2*cnt;
ans=min(ans,ct);
}
}while(next_permutation(p.begin(),p.end()));
return ans;
}
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
u--; v--;
if(u>v) swap(u,v);
g.insert({u,v});
}
cout<<solve()<<endl;
return 0;
}
E - LCM Sequence
Problem Statement
For a positive integer nn, define An as the least common multiple of 1,2,…,n.
You are given positive integers L and R. How many distinct integers are contained in the sequence (AL,AL+1,…,AR)?Constraints
- 1≤L≤R≤10^14
- R−L≤10^7
- L and R are integers.
解题思路:An表示1,2...n的最小公倍数, 求L...R的中不同数的个数
An 是一个单调不减的数列。
An 的值会变化(即 An>An−1)当且仅当 n 引入了新的质因子或新的质数的高次幂。
情况 1:n 是素数。
因为 n 是新的素数,之前 An−1 中不包含 n,所以 An=An−1×n。
情况 2:n 是某个素数 p 的高次幂(即 n=p^k, k≥2)。
此时 An−1 中已经包含 p,但可能不包含 pk 的足够高次幂。
例如:A4=12=LCM(1,2,3,4)。
4=2^2,而 A3=6=2×3 中 2 的最高次幂是 2。
因此 A4=12=2^2×3,比 A3 多了一个 2 的因子。
其他情况(n 是合数但不是质数的高次幂):
An 不会变化,因为 n 的所有质因子已经在 An−1 中以足够高的幂次出现。例如:A6=LCM(1,2,3,4,5,6)=60=A5(因为 6 = 2 × 3,而 2 和 3 已经在 A5 中)。
问题转化
根据上述分析:
序列 (AL,AL+1,…,AR) 中不同的值的数量, 等于 An 在 n∈[L,R] 中发生变化的次数加 1(初始的 AL)。
An的变化次数=区间(L,R]内素数的数量+区间(L,R]内质数高次幂的数量。
因此:
统计区间(L,R]内的素数数量cnt1。
统计区间(L,R]内的质数高次幂数量 cnt2。
最终答案=1 + cnt1 + cnt2。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll count_primes(ll l, ll r) {
ll a = sqrt(r);
vector<char> m(a + 1, true);
if (a >= 1) m[0] = m[1] = false;
vector<int> primes;
for (ll i = 2; i <= a; i++) {
if (m[i]) {
primes.push_back(i);
for (ll j = i * i; j <= a; j += i) {
m[j] = false;
}
}
}
ll s = r - l + 1;
vector<char> is_prime(s, true);
if (l == 1) is_prime[0] = false;
for (ll x : primes) {
ll st = max(x * x, ((l + x - 1) / x) * x);
for (ll y = st; y <= r; y += x) {
is_prime[y - l] = false;
}
}
return count(is_prime.begin(), is_prime.end(), true);
}
int main() {
ll l, r;
cin >> l >> r;
ll prime_cnt = count_primes(l + 1, r);
ll a = sqrt(r);
vector<char> m(a + 1, true);
if (a >= 1) m[0] = m[1] = false;
vector<int> primes;
for (ll i = 2; i <= a; i++) {
if (m[i]) {
primes.push_back(i);
for (ll j = i * i; j <= a; j += i) {
m[j] = false;
}
}
}
ll tot_cnt = 0;
for (int pr : primes) {
ll x = (ll)pr * pr;
while (x <= r) {
if (x > l) ++tot_cnt;
if (x > r / pr) break;
x *= pr;
}
}
cout << (1 + prime_cnt + tot_cnt) << endl;
return 0;
}
感谢大家的点赞和关注,你们的支持是我创作的动力!
吐槽:感觉最近异常倒霉啊...