前言
对于这一次比赛,好几次都是错在细节处。
A. Difficult Contest
题目传送门:Difficult Contest
这一题错的那几次就是没看见“NTT”,以为只有"FFT",结果错了几次,对于读题不认真也不是一次两次了,真难改这一毛病。
思路:
就是先排序,然后把T全部提到前面就行了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define ll long long
#define endl '\n'
const ll N=1e6+10;
void solve()
{
string s;
cin>>s;
if(s=="FFT")
{
cout<<"FTF"<<endl;
return ;
}
if(s=="NTT")
{
cout<<"TNT"<<endl;
return;
}
if(s.size()<3)
{
cout<<s<<endl;
return;
}
sort(s.begin(),s.end());
ll f=-1;
for(ll i=0;i+1<s.size();i++)
{
if(s[i]=='F'&&s[i+1]=='T'||s[i]=='N'&&s[i+1]=='T')
f=i;
}
if(f==-1)
cout<<s<<endl;
else
{
string ans,ans1;
ans=s.substr(f+1);
ans1=s.substr(0,f+1);
cout<<ans<<ans1<<endl;
}
}
signed main()
{
IOS;
ll t=1;
cin>>t;
while(t--)
solve();
return 0;
}
B. Left and Down
题目传送门:Left and Down
这也是一个思维题
思路:
分为两种情况,一种是如果存在最大公因数,且a和b除以这个最大公因数小于等于k则只需要一步,如果a和b原本就小于等于k也是步,然而其他都需要最少两步。
就以9 7 2来演示一下这两个都可以用(0,1)和(1,0)来进行解决。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define ll long long
#define endl '\n'
const ll N=1e6+10;
ll a,b,k;
void solve()
{
cin>>a>>b>>k;
ll s=__gcd(a,b);
a=a/s;
b=b/s;
if(k>=a&k>=b)
{
cout<<1<<endl;
return;
}
cout<<2<<endl;
}
signed main()
{
IOS;
ll t=1;
cin>>t;
while(t--)
solve();
return 0;
}
C. Count Good Numbers
题目传送门: Count Good Numbers
同样的思维题,也用到数论中的容斥原理
容斥原理
1.介绍
容斥原理是组合数学中用于计算多个集合的并集元素个数的重要原理。它通过 “包含” 与 “排斥” 的交替计算,解决了直接计算并集时因元素重复计数而产生的误差问题。
2.核心思想:
对于多个集合,计算它们的并集大小时:
先包含所有单个集合的元素个数;
再排斥掉所有两个集合交集的元素个数(因为它们被重复计算了);
接着包含所有三个集合交集的元素个数(因为它们被多排斥了);
以此类推,直到处理完所有集合的交集,最终得到并集的准确大小。
3.数学公式
设
A
1
,
A
2
,
…
,
A
n
是
n
个集合,
设 A_1, A_2, \dots, A_n是 n 个集合,
设A1,A2,…,An是n个集合,
则它们的并集元素个数为:
∣
A
1
∪
A
2
∪
⋯
∪
A
n
∣
=
∑
i
=
1
n
∣
A
i
∣
−
∑
1
≤
i
<
j
≤
n
∣
A
i
∩
A
j
∣
+
∑
1
≤
i
<
j
<
k
≤
n
∣
A
i
∩
A
j
∩
A
k
∣
−
⋯
+
(
−
1
)
n
+
1
∣
A
1
∩
A
2
∩
⋯
∩
A
n
∣
\left| A_1 \cup A_2 \cup \dots \cup A_n \right| = \sum_{i=1}^n |A_i| - \sum_{1 \leq i < j \leq n} |A_i \cap A_j| + \sum_{1 \leq i < j < k \leq n} |A_i \cap A_j \cap A_k| - \dots + (-1)^{n+1} |A_1 \cap A_2 \cap \dots \cap A_n|
∣A1∪A2∪⋯∪An∣=i=1∑n∣Ai∣−1≤i<j≤n∑∣Ai∩Aj∣+1≤i<j<k≤n∑∣Ai∩Aj∩Ak∣−⋯+(−1)n+1∣A1∩A2∩⋯∩An∣
符号规律:
奇数个集合的交集前为 “+”,偶数个集合的交集前为 “-”。
直观理解(以 2 个集合为例)
若有两个集合 A 和 B,它们的并集元素个数为:
∣
A
∪
B
∣
=
∣
A
∣
+
∣
B
∣
−
∣
A
∩
B
∣
|A \cup B| = |A| + |B| - |A \cap B|
∣A∪B∣=∣A∣+∣B∣−∣A∩B∣
(减去交集是因为
A
∩
B
A \cap B
A∩B 的元素在 |A| 和 |B| 中被重复计算了一次)。
扩展到 3 个集合 (A, B, C):
∣
A
∪
B
∪
C
∣
=
∣
A
∣
+
∣
B
∣
+
∣
C
∣
−
∣
A
∩
B
∣
−
∣
A
∩
C
∣
−
∣
B
∩
C
∣
+
∣
A
∩
B
∩
C
∣
|A \cup B \cup C| = |A| + |B| + |C| - |A \cap B| - |A \cap C| - |B \cap C| + |A \cap B \cap C|
∣A∪B∪C∣=∣A∣+∣B∣+∣C∣−∣A∩B∣−∣A∩C∣−∣B∩C∣+∣A∩B∩C∣
(先加单个集合,减两两交集,再加三个集合的交集 —— 因为它在前面的步骤中被多减了一次)。
4.应用场景
容斥原理广泛用于:
计数问题:
计算 “不满足某些条件” 或 “至少满足一个条件” 的元素个数(如本文中 “不是 2、3、5、7 倍数的数”)。
概率计算:
多个事件并集的概率。
数论:
计算与某些数互质的数的个数(如欧拉函数的推广)。
排列组合:
计算有限制条件的排列数(如错排问题)。
为什么需要容斥原理?
问题的本质是:
计算区间内不被 2、3、5、7 整除的数的个数。
如果直接遍历区间内的每个数并检查是否符合条件,在数据范围大时会超时。而容斥原理可以通过数学公式直接计算结果,时间复杂度为 O (1),非常高效。
容斥原理的核心思路
容斥原理( Inclusion-Exclusion Principle )用于计算 “多个集合的并集” 的元素数量,进而推导出 “不被任何集合包含” 的元素数量。
对于本题,我们定义 4 个集合:
A:能被 2 整除的数
B:能被 3 整除的数
C:能被 5 整除的数
D:能被 7 整除的数
我们的目标是计算:总数 - (A∪B∪C∪D 的元素数量),即 “不被 2、3、5、7 中任何一个整除的数”。
1.基础总数:
区间内的数字总数(x)。
2.减去单个集合的数量:
减去能被 2、3、5、7 单独整除的数(这些数属于 A、B、C、D 中的一个)。
- x/2 - x/3 - x/5 - x/7
-
单个集合中
a集合:a,ab,ac,ad,abc,abd,acd,abcd;
b集合:b,ab,bc,bd,abc,abd,bcd,abcd;
c集合:c,ac,bc,cd,abc,acd,bcd,abcd;
d集合:d,ad,bd,cd,abd,acd,bcd,abcd;
由此可见被两个数整除的减去了2次。
被3个数整除的减去了3次。
被4个数整除的减去了4次。
3.加回两个集合的交集:
因为步骤 2 中,同时被两个数整除的数(如能被 2 和 3 同时整除的数)被减了两次,需要加回一次。
+ x/6 + x/10 + x/14 + x/15 + x/21 + x/35
(6=2×3,10=2×5,14=2×7,15=3×5,21=3×7,35=5×7,对应所有两两交集)
ab集合:ab,abc,abd,abcd.
ac集合:ac,abc,acd,abcd.
ad集合:ad,abd,acd,abcd.
bc集合:bc,abc,bcd,abcd.
bd集合:bd,abd,bcd,abcd.
cd集合:cd,acd,bcd,abcd.
由此可以看出
被2个数整除的加了1次
被3个数整除的加了3次
被4个数整除的加了6次
4.减去三个集合的交集:
步骤 3 中,同时被三个数整除的数(如能被 2、3、5 同时整除的数)被加回了三次,需要再减去一次。
- x/30 - x/42 - x/70 - x/105
(30=2×3×5,42=2×3×7,70=2×5×7,105=3×5×7,对应所有三个集合的交集)
abc集合:abc,abcd
abd集合:abd,abcd
bcd集合:bcd,abcd
acd集合:acd,abcd
被3个数整除的减去了1次
被4个数整除的减去了4次
5.加回四个集合的交集:
步骤 4 中,同时被四个数整除的数(能被 2×3×5×7=210 整除的数)被减了四次,需要最后加回一次。
+ x/210
abcd
被4个数整除的加了1次
以此综合
均被减去一次
最后
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define ll long long
#define endl '\n'
const ll N=1e6+10;
ll res(ll x)
{
return x-x/2-x/3-x/5-x/7+x/6+x/10+x/14+x/15+x/21+x/35-x/30-x/42-x/70-x/105+x/210;
}
void solve()
{
ll l,r;
cin>>l>>r;
cout<<res(r)-res(l-1)<<endl;
}
signed main()
{
IOS;
ll t=1;
cin>>t;
while(t--)
solve();
return 0;
}
总结
看来还是没有适应那个时间段,同时犯的错误太多了,只能说下次尽力!