感觉今晚的题目偏思维为主,需要思考
A题题解
因为可以选一个数去赋值,想让数组和变成奇数
那么数组里面必须存在奇数。注意如果是全偶数或者N个数全是奇数但是加来的和是偶数,这都是变不出来的
#include<bits/stdc++.h>
using namespace std;
int A[2005];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
int s=0;
int J=0;
for(int i=1;i<=n;i++){
scanf("%d",&A[i]);
s=s+A[i]%2;
if(A[i]%2)J++;
}
s=s%2;
if(s==0&&J==0||s==0&&J==n)printf("NO\n");//全偶全奇数
else printf("YES\n");
}
return 0;
}
B题题解
实际上你会发现,如果你每次都全部拿去买东西,一定会把个位上面的亏完,所以我们的策略是每次拿全部大于等于10的整的部分去买东西, 去算返现,把个位留着,加上返现进行下一轮计算
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
int s=0;
while(n>=10){
s=s+n/10*10;
n=n%10+(n/10);
}
printf("%d\n",s+n);
}
return 0;
}
C题题解
经典的问题
我们考虑移动的字符串
假如我从起点
S
[
1
]
S[1]
S[1]开始走到
S
[
k
]
S[k]
S[k]到达点
(
X
,
Y
)
(X,Y)
(X,Y) 接着继续走一段又到达
(
X
,
Y
)
(X,Y)
(X,Y),实际上完全可以把
S
[
k
]
S[k]
S[k]后面这一段删了。根据这个思路我们就去记录,到达每个点走了多少步操作数。 这里涉及到坐标的印射,最好使用pair<元素类型,元素类型>+map 去映射 ,pair<>记录的就是二元组,我们可以映射map<pair<元素,元素>,元素> vis ,使用的时候就是vis[make_pari(a,b)]= ?
#include<bits/stdc++.h>
using namespace std;
char s[200005];
map<pair<int,int>,int>mp;
int main() {
int p;
scanf("%d",&p);
while(p--) {
int n;
scanf("%d%s",&n,s+1);
int d=1e9;
int x=0,y=0,l=-1,r=-1;
mp[{0,0}]=0;
for(int i=1; i<=n; i++) {
if(s[i]=='L')
x++;
if(s[i]=='R')
x--;
if(s[i]=='U')
y++;
if(s[i]=='D')
y--;
if(mp.count({x,y})!=0) {
//如果当前这个点 在前面已经经过,那么我们尝试删除这段区间
//取最小删除区间
if( (i-mp[{x,y}]) <d){
d=i-mp[{x,y}];
l=mp[{x,y}]+1,r=i;
}
}
mp[{x,y}]=i;
}
if(l==-1||r==-1) printf("-1\n");
else printf("%d %d\n",l,r);
mp.clear();//清空标记
}
return 0;
}
D题 戒网瘾
实际上玩游戏也是需要策略的
具体思路写在代码里面了。能由自己拿分就不用管太多。
不能自己正常拿分那要考虑使用卷轴
#include<bits/stdc++.h>
using namespace std;
int num[200009],e=0,add2=0,y=0;
int hp[200009],n,a,b,k,add=0,r,change=0;
int main() {
scanf("%d%d%d%d",&n,&a,&b,&k);
for(int i=1; i<=n; i++) {
scanf("%d",&hp[i]);
}
for(int i=1; i<=n; i++) {
int le=hp[i]%(a+b);//前置双人出击很多轮先消掉,再讨论
if(le==0){
//刚好整除说明由对手完成最后一击,是没有分数的
//倒退回去一轮,依然由自己先手攻击
//讨论延迟对手几次 能击杀怪物获得分数
le=a+b;
}
if(le<=a){
//双人合击后,现在由自己先手,如果怪物的血能被自己一击必杀
//那么能拿到分数,无需多余讨论
add++;
continue;
}
if(le-a>0){
//自己一刀杀不死
//a砍不死
//但是对手补一刀怪物必死
//计算要延迟对手多少轮
le=le-a;//自己先砍一刀
if(le%a==0) {//接下来全由自己攻击,计算次数
num[++e]=le/a;
} else {
num[++e]=le/a+1;
}
}
}
sort(num+1,num+e+1);
//对需要延迟对手攻击,才能取得分数的怪物排序
//按延迟次数从小到大排序,因为我们的卷轴有限
for(int i=1; i<=e; i++) {
add2=add2+num[i];
if(add2<=k) {
y++;
}else {//卷轴不够了
break;
}
}
printf("%d",add+y);
return 0;
}