A.LCM Problem
题意:给定两个整数定义的闭区间
[
l
,
r
]
[l,r]
[l,r],让你在区间内找出两个数
x
,
y
x,y
x,y满足
L
C
M
(
x
,
y
)
≤
r
LCM(x,y) \le r
LCM(x,y)≤r;
思路:容易验证
L
C
M
(
x
,
y
)
LCM(x,y)
LCM(x,y)至少是
m
i
n
(
x
,
y
)
min(x,y)
min(x,y)的二倍,所以直接构造一组最小的解
(
l
,
2
l
)
(l,2l)
(l,2l)
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
while(t--){
long long l,r;
cin>>l>>r;
if(l*2<=r) cout<<l<<' '<<2*l<<endl;
else cout<<"-1 -1"<<endl;
}
return 0;
}
B.Array Walk
题意:给定一个序列
{
a
1
,
a
2
,
a
3
,
.
.
.
,
a
n
}
\{a_1,a_2,a_3,...,a_n\}
{a1,a2,a3,...,an},你一开始站在1的位置并且拥有权值
a
1
a_1
a1,你可以向右或向左走,每走到一个位置,权值和就加上此位置的权值,限制是可以不能连续向左走。例如移动序列可以是
{
1
,
2
,
1
,
2
,
1
,
2
}
\{1,2,1,2,1,2 \}
{1,2,1,2,1,2}但是不能是
{
1
,
2
,
3
,
2
,
1
}
\{1,2,3,2,1\}
{1,2,3,2,1},问走
k
k
k步,最多向左走
z
(
z
≤
5
)
z(z\le5)
z(z≤5)步,最后权值和最大是多少。
思路:首先计算全部向右走的和
s
u
m
[
k
+
1
]
sum[k+1]
sum[k+1],并处理过程中相邻两格的和(考虑向左一步又向右一步的走法),当最大的相邻和所在两格不是最后两格的时候,我们选择将最后的向右两步走变为在最大相邻和的地方左右走,序列结束的位置
e
d
ed
ed也就相应往左移两位,由于
z
z
z比较小,可以枚举向左走
(
1
−
z
)
(1-z)
(1−z)步的情况取最大值。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
ll sum[maxn],a[maxn],s2[maxn];
int main() {
int t;
cin>>t;
ll n,k,z;
while(t--){
cin>>n>>k>>z;
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<n;i++) s2[i]=a[i]+a[i+1];
ll ans=sum[k+1],ed=k+1,m=-1;
for(int p=1;p<=z;p++){
ed=k+1-p*2;
m=-1;
if(ed<1) break;
for (int i = 1; i <= ed; i++) m=max(m,s2[i]);
ans = max(sum[ed]+ m*p,ans);
}
cout<<ans<<endl;
}
return 0;
}
C. Good String
题意:给定一个由
0
∼
9
0\sim9
0∼9 构成的字符串
s
=
t
1
t
2
⋯
t
n
s=t_1t_2⋯t_n
s=t1t2⋯tn,询问最少从
s
s
s中删除几个字符,使得新得到的字符串满足:
t
2
t
3
⋯
t
n
−
1
t
n
t
1
=
t
n
t
1
t
2
⋯
t
n
−
2
t
n
−
1
t_2t_3⋯t_{n−1}t_nt_1=t_nt_1t_2⋯t_{n−2}t_{n−1}
t2t3⋯tn−1tnt1=tnt1t2⋯tn−2tn−1 。
思路:容易得到:
t
1
=
t
3
=
t
5
=
⋅
⋅
⋅
∩
t
2
=
t
4
=
⋅
⋅
⋅
t
n
t_1=t_3=t_5=··· \cap t_2=t_4=···t_n
t1=t3=t5=⋅⋅⋅∩t2=t4=⋅⋅⋅tn因此,该字符串的构成最多只有两种字符,并且有两种字符时,必定形如
121212
⋯
121212⋯
121212⋯的形式。由于该字符串由
0
∼
9
0\sim 9
0∼9 构成,一共只有
10
×
10
+
10
10\times 10+10
10×10+10 种情况(相邻的两位数的情况、全部数字相同),直接暴力枚举即可。
记录错误:这里要注意的是形如
2323213232323
2323213232323
2323213232323这种两两重复但是中间插了一个数字的情况,一开始我并没有考虑到,只进行了相邻的数字数量计数,错误代码会输出3,正确的做法应该是枚举
1
∼
99
1\sim99
1∼99的所有数字,计算如果只保留这两种数字的交替出现,应该删除多少字符;然后算一下只保留一种字符需要删除的字符数量,二者取一个
m
i
n
min
min即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
ll sum[111],cnt[11];
int main() {
int t;
cin>>t;
ll n,k,z;
while(t--){
memset(sum,0,sizeof(sum));
memset(cnt,0,sizeof(cnt));
string str;
cin>>str;
int len=str.size();
if(len<=2){
cout<<0<<endl;
continue;
}
for(int i=0;i<len;i++) cnt[str[i]-'0']++;
ll m=-1,mm=-1;
for(int a=0;a<10;a++){
for(int b=0;b<10;b++){
m=0;
for(int i=0;i<len;i++){
int x=str[i]-'0';
if(m&1){
if(x==a) m++;
}
else{
if(x==b) m++;
}
}
m-=(m&1);
mm=max(mm,m);
}
}
m=-1;
for(int i=0;i<10;i++) m=max(m,cnt[i]);
cout<<min(len-m,len-mm)<<endl;
}
return 0;
}
这场分掉的真难受,都是思路对了但是最后写炸了;接下来会补题