题目链接:https://codeforces.com/contest/1996
写在前面
这场div.3难度比以前更大一些,一道C题想了半天都想不出来,导致这场比赛直接寄了·····,打的非常烂(不如直接摆烂睡觉:()
A-Legs
思路
考点:贪心
签到题,为了使动物尽可能小,**先考虑牛在考虑鸡(坤)**即可
编程
void solve(){
int n;cin >> n;
int ans=n/4;
n%=4;
ans+=n/2;
cout << ans << endl;
return ;
}
B-Scale
思路
题目最关键的一行:
由此可知,题目保证划分好的区域内的值相等,我们每次只需要取每个区域内第一个值就行
编程
void solve(){
int n,k;cin >> n >> k;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
cin >> a[i][j];
for(int i=1;i<=n;i+=k){
for(int j=1;j<=n;j+=k){
cout << a[i][j];
}
cout << endl;
}
return ;
}
C- Sort
思路
考点:模拟+前缀和
如果我们每次询问都进行暴力模拟,那必然会超时
因此,对于这题我们可以考虑用前缀和,在询问之前进行预处理
对于区间l,r的最小操作就是区间不同数的一半,在最后我们需要将答案除以2即可
编程
const int N=2e5+5;
int a[N][27],b[N][27];
void solve(){
int n,q;
cin >> n >> q;
string s,t;
cin >> s >> t;
s = " "+ s;
t= " " + t;
for(int i=1;i<=n;++i){
for(int j=0;j<26;++j){
a[i][j]=a[i-1][j];
b[i][j]=b[i-1][j];
}
++a[i][s[i]-'a'];
++b[i][t[i]-'a'];
}
while(q--){
int l,r;
cin >> l >> r;
int ans=0;
for(int j=0;j<26;++j){
ans+=abs((a[r][j]-a[l-1][j])-(b[r][j]-b[l-1][j]));
}
cout << ans/2 << endl;
}
return ;
}
D-Fun
思路
考点:数学思维
对于a,b,c三个数,我们先考虑a的范围
对于
a
b
+
a
c
+
b
c
≤
n
ab+ac+bc≤n
ab+ac+bc≤n 这个式子,我们令 b=1,c=1,这个式子近似于
a
+
a
≤
n
a+a≤n
a+a≤n,因此a的取值范围在
[
1
,
n
/
2
]
[1,n/2]
[1,n/2]
然后我们在考虑b的范围,假设c=0,
a
∗
b
≤
n
a*b≤n
a∗b≤n,因此b的范围为
[
1
,
n
/
a
)
[1,n/a)
[1,n/a)
对于c,如果我们在套一层循环可能会超时,观察式子,循环中每次算出来的c都是最大值
因此c的取值范围在1~max,我们只需要将答案加上max即可
由于c需要满足两个条件,一个是
a
b
+
a
c
+
b
c
≤
n
ab+ac+bc≤n
ab+ac+bc≤n ,转换一下为
c
≤
(
n
−
a
∗
b
)
/
(
a
+
b
)
c≤(n-a*b)/(a+b)
c≤(n−a∗b)/(a+b)
另一个是
c
≤
x
−
a
−
b
c≤x-a-b
c≤x−a−b ,数学中两个小于号取其中最小的那个数
到此本题就出来了
编程
void solve(){
int n,x;
cin >> n >> x;
int ans=0;
for(int a=1;a<=n/2;++a)
for(int b=1;b<n/a;++b){
if(a*b>=n) break;
if(x-a-b<0) break;
ans+=min(x-a-b,(n-a*b)/(a+b));
}
cout << ans << endl;
return ;
}
E-Decode
思路
对于一段区间
[
l
,
r
]
[l,r]
[l,r],如果区间内0和1的个数相等那么这个区间对会使答案加
l
∗
(
n
−
r
+
1
)
l*(n-r+1)
l∗(n−r+1)
问题就转移成怎么快速求出所有有效区间的位置
这里可以维护一个当前值now,遇到0减一,遇到1加一
如果一个区间1和0的数量相同的话,那么这个区间
[
l
,
r
]
[l,r]
[l,r] 在
[
l
−
1
,
r
]
、
[
l
−
2
,
r
]
、
[
l
,
r
+
1
]
、
[
l
,
r
+
2
]
[l-1,r]、[l-2,r]、[l,r+1]、[l,r+2]
[l−1,r]、[l−2,r]、[l,r+1]、[l,r+2]··· 都是相同的
可以开一个map来记录每一个i的当前值对应的左部分的和,对于位置为i对答案的贡献就是
m
[
n
o
w
]
∗
(
n
−
i
+
1
)
m[now]*(n-i+1)
m[now]∗(n−i+1)
编程
void solve(){
string s;cin >> s;
int n=s.size();
s= " " + s;
unordered_map<int,int> m;
int now=0,ans=0;
m[0]=1;
for(int i=1;i<=n;++i){
if(s[i]=='0') now--;
else now++;
ans+=m[now]*(n-i+1);
ans%=mod;
m[now]+=i+1;//加i即加上左部分的和,加1为了后面遇到相同的now,先加上1
}
cout << ans << endl;
return ;
}