2 条题解
-
6
修正一下题目, 是原序输出, 是逆序输出。
简单模拟题,按照题目意思模拟即可,但是坑点很多。
以下默认 :
- 对于 ,直接枚举 ,输出小写字母。
- 对于 ,和 反一下,输出大写字母。
- 对于 ,输出 。
每个字符重复输出 次。
如果 ,则从 倒着枚举。
srds:
- 符号左、右边一端字母,一端数字,应当输出 。
- 如果出现类似于 的数据,输出 。
- 如果 ,输出 ,譬如:。
#include <bits/stdc++.h> using namespace std; #define int long long #define rep(i,x,y) for(int i=x;i<=y;i++) #define rrep(i,x,y) for(int i=x;i>=y;i--) #define pr printf #define inf 1e9 #define lowbit(x) x & (-x) const int N=1e6+10; inline int read() { int s = 0, w = 1; char c = getchar(); while (!isdigit(c)) { if (c == '-') w = -1; c = getchar(); } while (isdigit(c)) { s = (s << 1) + (s << 3) + (c ^ 48); c = getchar(); } return s * w; } int p1,p2,p3; string s; inline void small(char x){//转小写或者不转。 if(isdigit(x)) cout<<x; else if(x >= 'A' && x <= 'Z') cout<<char(x+32); else cout<<x; } inline void big(char x){//转大写或者不转。 if(isdigit(x)) cout<<x; else if(x >= 'a' && x <= 'z') cout<<char(x-32); else cout<<x; } inline void judge(int sr , int ed){ /* 分情况讨论。*/ if(p1==1){ if(p3==2) rrep(i,s[ed]-1,s[sr]+1) rep(j,1,p2) small(char(i)); else rep(i,s[sr]+1,s[ed]-1) rep(j,1,p2) small(char(i)); } if(p1==2){ if(p3==2) rrep(i,s[ed]-1,s[sr]+1) rep(j,1,p2) big(char(i)); else rep(i,s[sr]+1,s[ed]-1) rep(j,1,p2) big(char(i)); } if(p1==3) rep(i,s[sr]+1,s[ed]-1) rep(j,1,p2) pr("*"); } signed main() { p1=read();p2=read();p3=read(); cin>>s; int len=s.size(); rep(i,0,len-1){ if(s[i]!='-') cout<<s[i]; else{ if(isdigit(s[i-1])&&isalpha(s[i+1])) pr("-"); else if(isalpha(s[i-1])&&isdigit(s[i+1])) pr("-"); else if(s[i-1]=='-'||s[i+1]=='-') pr("-"); else if(s[i-1] >= s[i+1]) pr("-"); else if(!isalnum(s[i-1])||!isalnum(s[i+1])) pr("-"); else judge(i-1,i+1); } } return 0; }
-
1
Be Patient and Slow!!!
一.题目简介
- 同时遇到下面的情况需要做字符串的展开:
- 在输入的字符串中,出现了减号“-”;
- 减号两侧同为小写字母或同为数字;
- 且按照ASCII码的顺序,减号右边的字符严格大于左边的字符。
- 共有三个参数:p1,p2,p3。
- p2:p2=k表示同一个字符要连续填充k个。
- p3:是否改为逆序:p3=1表示维持原来顺序,p3=2表示采用逆序输出。
- p1:这个是最复杂的:p1=1时,对于字母子串,填充小写字母;p1=2时,对于字母子串,填充大写字母。这两种情况下数字子串的填充方式相同。p1=3时,不论是字母子串还是数字字串,都用与要填充的字母个数相同的星号“*”来填充。
二.讲思路(多写几个Function思路就清晰了)
- 写一个inline void work(int l,int r)函数:
-
work(a,b)就是负责输出s[a]和s[b]之间的展开式;
-
Example:当主串:a-d,p1=1,p2=2,p3=1时,work(0,2)输出"abbccd";
-
在主函数遍历s时,if(s[i]=='-') work(i-1,i+1); 在这种情况下:s[i]处理了后,那么对于s[i+1]:它的上一个字符s[i]就是'-',并且在work(i-1,i+1)时已经输出s[i+1],所以就直接跳到s[i+2];
-
if(s[i]!='-') 直接输出s[i];#### 真的就这么简单吗?
其实不然,举个例子 当主串为:a-b-c时,此时参数p已经不重要了,答案始终是:abc。然而,按照我们刚才的思路:
- i=0: printf(a);
- i=1: printf(ab);
- i=2: printf(b);
- i=3: printf(bc);
- i=4: printf(c);
这样答案就成了aabbbcc:输出出现了重复; 解决:* if(s[i]!='-'),输出s[i]后还要标记used[i]=1;表示i号字符已经处理并输出。
- if(s[i]=='-'),work(i-1,i+1)时就要判断s[i-1]已经处理没有,及如果used[i]=1,就不输出s[i-1];并且work()之后还要标记used[i+1]=1;
-
还有一点:主函数循环遍历s时是从0~len(=s.size())-1-1,也就是把是s[len-1] (最后一位单独处理): if(!used[len-1]) printf("%c",s[len-1]);因为如果s[len-1-1]!='-',那么s[len-1]就不会被输出。
-
现在上主函数代码
int main(){ ios::sync_with_stdio(0); cin>>p1>>p2>>p3>>s; int len=s.size(); printf("%c",s[0]); used[0]=1; for(int i=1;i<len-1;i++){ if(s[i]=='-'){ work(i-1,i+1); used[i+1]=1; i+=1;continue; } printf("%c",s[i]); used[i]=1; } if(!used[len-1]) printf("%c",s[len-1]); return 0; }
- 详解work(int l,int r)函数.
- 如果s[l],s[r]同为数字或字母:
- 如果s[l]<s[r]//符合规范,可以展开;
- 判断s[l]是否已经被处理过,还未被处理过才输出s[l];
- 如果p1=3,数字和字母都一样:填充'*'即可,并且不用管p3,因为此时逆序和顺序都一样了,考虑写一个inline void fillstar(int a,int b)函数,执行fillstar(int(s[l])+1,int(s[r])-1);
- 如果p1=1或2,此时就要考虑p3,所以写一个inline void reverse(int a,int b)函数。执行reverse(int(s[l])+1,int(s[r])-1);
- 输出s[r]并返回;
- 如果s[l]>=不合规范;
- 判断s[l]是否已经被处理过,还未被处理过才输出s[l];
- 输出"-"和s[r]并返回;
- 如果s[l],s[r]同为数字或字母:
现在上work()函数代码
inline void work(int l,int r){ if(isalpha(s[l])&&isalpha(s[r])||isdigit(s[l])&&isdigit(s[r])){ if(s[l]<s[r]){ if(!used[l]) printf("%c",s[l]); if(p1==1||p1==2) {reverse(int(s[l])+1,int(s[r])-1);}//reverse函数把两种情况一同解决了 if(p1==3) {fillstar(int(s[l])+1,int(s[r])-1);} printf("%c",s[r]); return; } } if(!used[l]) printf("%c",s[l]); printf("-%c",s[r]); }
现在上fillstar()函数代码
inline void fillstar(int l,int r){//如果p1=3,输出'*' for(int i=l;i<=r;i++) for(int j=1;j<=p2;j++) printf("*"); }
现在上reverse()函数代码
inline void reverse(int l,int r){ if(p3==1){ for(int i=l;i<=r;i++) for(int j=1;j<=p2;j++) printf("%c",deal(char(i)));//deal函数处理大小字母的情况 } if(p3==2){ for(int i=r;i>=l;i--) for(int j=1;j<=p2;j++) printf("%c",deal(char(i)));//deal函数处理大小字母的情况 } }
现在上deal()函数代码
inline char deal(char x){ if(isdigit(x)) return x;//如果是x数字,就直接返回x if(p1==1) return x;//如果p1=1,输出小写字母 return x-'a'+'A';//如果p1=2,输出所对应的大写字母 }
三.完整AC代码(30MS完事)
#include<bits/stdc++.h> using namespace std; int p1,p2,p3,len; string s; bool used[110]; inline char deal(char x){ if(isdigit(x)) return x;//如果是x数字,就直接返回x if(p1==1) return x;//如果p1=1,输出小写字母 return x-'a'+'A';//如果p1=2,输出所对应的大写字母 } inline void reverse(int l,int r){ if(p3==1){ for(int i=l;i<=r;i++) for(int j=1;j<=p2;j++) printf("%c",deal(char(i)));//deal函数处理大小字母的情况 } if(p3==2){ for(int i=r;i>=l;i--) for(int j=1;j<=p2;j++) printf("%c",deal(char(i)));//deal函数处理大小字母的情况 } } inline void fillstar(int l,int r){//如果p1=3,输出'*' for(int i=l;i<=r;i++) for(int j=1;j<=p2;j++) printf("*"); } inline void work(int l,int r){ if(isalpha(s[l])&&isalpha(s[r])||isdigit(s[l])&&isdigit(s[r])){ if(s[l]<s[r]){ if(!used[l]) printf("%c",s[l]); if(p1==1||p1==2) {reverse(int(s[l])+1,int(s[r])-1);}//reverse函数把两种情况一同解决了 if(p1==3) {fillstar(int(s[l])+1,int(s[r])-1);} printf("%c",s[r]); return; } } if(!used[l]) printf("%c",s[l]); printf("-%c",s[r]); } int main(){ ios::sync_with_stdio(0); cin>>p1>>p2>>p3>>s; int len=s.size(); printf("%c",s[0]); used[0]=1; for(int i=1;i<len-1;i++){ if(s[i]=='-'){ work(i-1,i+1); used[i+1]=1; i+=1;continue; } printf("%c",s[i]); used[i]=1; } if(!used[len-1]) printf("%c",s[len-1]); return 0; }
四.总结:
遇到复杂的大模拟类问题时
-
先想好共有多少种不同的情况;
-
看这几种情况有没有能够合并在一起解决的;
-
尽量多写点函数,便于理思路。
什么,你觉得太长,给你缩短一下(代价就是时间变长):
#include <bits/stdc++.h>using namespace std;int p1,p2,p3,i=0,k;char ch[300],be,af,f,j,p;//p用于输出;int main() {scanf("%d%d%d%s",&p1,&p2,&p3,ch);//输入;while(ch[i]){//当ch[i]有值时;be=ch[i-1];af=ch[i+1];f=ch[i];//f存储ch[i],便于判断;if(f=='-'&&af>be&&(be>='0'&&af<='9'||be>='a'&&af<='z')){//意思是ch[i]若为'-',就判断其前后是否满足条件,满足进入循环;for(p3==1?j=be+1:j=af-1; p3==1?j<af:j>be; p3==1?j++:j--){p=j;//j是整形变量,p是字符型变量,这样是将p赋值为ASCII码为j的字符;if(p1==2)//是否大写;p=(p>='a')?p-32:p;//如果是字母就转成大写else if(p1==3) p='*';//是否输出'*'for(k=0; k<p2; k++)//输出p2个printf("%c",p);}}elseprintf("%c",f);//如果ch[i]是非'-'或者其前后不满足条件,就原样输出;i++;//一定要放在后面,不然会出错QAQ;}return 0;}
看了这么久,交个学费不过分吧(点个赞)
- 同时遇到下面的情况需要做字符串的展开:
- 1
信息
- ID
- 185
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 245
- 已通过
- 79
- 上传者