甲级题目较难,所以我分类,写了部分题目。
乙级题目的代码在我前一篇博文里,为了方便找,就把所有代码写在了一篇文章,没有写思路。
甲级题目我会尽力写点思路和注释,大家一起学习,供参考…
都在一个class文件写的,所以头文件基本不改动(偷个懒),不是都需要那么多头文件的
目录
- A 1042 Shuffling Machine
- A 1046 Shortest Distance
- A 1065 A+B and C (64bit)
- A 1002 A+B for Polynomials
- A 1009 Product of Polynomials
- A 1011 World Cup Betting
- A 1006 Sign In and Sign Out
- A 1036 Boys vs Girls
- A 1031 Hello World for U
- A 1019 General Palindromic Number
- A 1027 Colors in Mars
- A 1058 A+B in Hogwarts
- A 1001 A+B Format
- A 1005 Spell It Right
- A 1035 Password
- A 1077 Kuchiguse
- A 1082 Read Number in Chinese
A 1042 Shuffling Machine
思路:
(1)三个数组: 存放换序前,换序后,换序规则;
操作一次,end【】覆盖start【】
(2)char数组来保存花色
(3)编号与花色的关系:注意编号减1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1000010;
char mp[5]={'S','H','C','D','J'};
int start[55],en[55],nex[55];
int main()
{
int k,i,j;
cin>>k;
for(i=1;i<=54;i++)
{
start[i]=i;
}
for(i=1;i<=54;i++)
{
cin>>nex[i];
}
for(j=0;j<k;j++)
{
for(i=1;i<=54;i++)
{
en[nex[i]]=start[i];
}
for(i=1;i<=54;i++)
{
start[i]=en[i];
}
}
for(i=1;i<=53;i++)
{
start[i]--;
cout<<mp[start[i]/13]<<start[i]%13+1<<" ";
}
start[i]--;
cout<<mp[start[i]/13]<<start[i]%13+1;
return 0;
}
A 1046 Shortest Distance
思路:
用dis[maxn]来表示号节点按顺时针方向到i号节点的距离,并且在输入时就开始记录更新,sum来表示一整圈的距离,对于每一个查询,就是dis(left,right)与sum-dis(left,right)之间的最小值
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1000010;
int dis[maxn];//1号节点按顺时针方向到i号节点的距离
int a[maxn];//i号与i-1号之间的距离
int main()
{
int n,m,left,right,i,j,sum=0;
cin>>n;
for(i=2;i<=n+1;i++)
{
cin>>a[i];
sum+=a[i];
dis[i]=sum;
}
cin>>m;
for(j=0;j<m;j++)
{
cin>>left>>right;
if(left>right)
swap(left,right);
int temp=dis[right]-dis[left];
int k=min(temp,sum-temp);
cout<<k<<endl;
}
return 0;
}
A 1065 A+B and C (64bit)
思路:
由样例可知数据范围很大,long long型也是不够的,该题如果用字符串比较也可,但是过于麻烦,A+B是有可能溢出的,而我们恰恰可以利用溢出的特性来进行判断。
(1)正溢出:A+B>C
(2)负溢出:A+B<C
(3)无溢出时正常比较
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1000010;
int dis[maxn];//1号节点按顺时针方向到i号节点的距离
int a[maxn];//i号与i-1号之间的距离
int main()
{
int n,i,k=1;
long long a,b,c;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a>>b>>c;
long long res=a+b;
bool flag;
if(a>0&&b>0&&res<0)
flag=true;
else if(a<0&&b<0&&res>=0)
flag==false;
else if(res>c)
flag=true;
else flag=false;
if(flag==true)
printf("Case #%d: true\n",k++);
else
printf("Case #%d: false\n",k++);
}
return 0;
}
A 1002 A+B for Polynomials
思路:
这一题感觉就是划水题,没有什么难点,就是hash的应用。
唯一需要注意的点就是最后输出格式,用prinf,因为浮点数保留一位小数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 10010;
double p[maxn]={0};
int main()
{
int n,m,i,k;
double a,b,c;
cin>>n;
for(i=0;i<n;i++)
{
cin>>k>>a;
p[k]+=a;
}
cin>>m;
for(i=0;i<m;i++)
{
cin>>k>>a;
p[k]+=a;
}
int count=0;
for(i=0;i<maxn;i++)
{
if(p[i]!=0)
count++;
}
cout<<count;
for(i=maxn-1;i>=0;i--)
{
if(p[i]!=0)
{
printf(" %d %.1f",i,p[i]);
}
}
return 0;
}
A 1009 Product of Polynomials
思路:
这一题就是上面一题的升级版,也是hash应用,但是不能全部是hash,否则遍历第一个多项式的范围会特别大。
因此,采用结构体来暂存数据。
(1)结构体保存第一个多项式的信息(指数和系数)
(2)输入第二个多项式信息,扫描第一个结构体,改变指数和系数,将结果保存在hash表中(即数组ans)
(3)扫面数组ans,输出
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 10010;
double ans[maxn]={0.0};
struct Poly
{
int exp;
double cof;
}poly[maxn];
int main()
{
int n,m,i,j;
cin>>n;
for(i=0;i<n;i++)
{
cin>>poly[i].exp>>poly[i].cof;
}
cin>>m;
int a;
double b;
for(i=0;i<m;i++)
{
cin>>a>>b;
for(j=0;j<n;j++)
{
ans[a+poly[j].exp]+=b*poly[j].cof;
}
}
int count=0;
for(i=0;i<maxn;i++)
{
if(ans[i]!=0)
count++;
}
cout<<count;
for(i=maxn-1;i>=0;i--)
{
if(ans[i]!=0)
{
printf(" %d %.1f",i,ans[i]);
}
}
return 0;
}
A 1011 World Cup Betting
思路:
划水题吧~~
理解题目意思就行。输入三行,找出每行最大值,然后计算即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//const int maxn = 10010;
char s[3]={'W','T','L'};
int main()
{
int n,m,i,j,k;
double a;
double maxn;
double ans=1.0;
for(i=0;i<3;i++)
{
maxn=0.0;
for(j=0;j<3;j++)
{
cin>>a;
if(a>maxn)
{
k=j;
maxn=a;
}
}
cout<<s[k]<<" ";
ans*=maxn;
}
printf("%.2f",(ans*0.65-1)*2);
return 0;
}
A 1006 Sign In and Sign Out
思路:
这题也不难。还是用结构题存储数据,但是注意不要以一个人全部信息作为结构题内容。而是把签到签离时间都平等看待,找出其中最大值即为最后一个锁门的,最小值就是最早开门的。
比较写一个cmp函数,分层比较即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//const int maxn = 10010;
struct pnode
{
string id;
int hour;
int minute;
int seconds;
}node,early,late;
bool cmp(pnode a,pnode b)
{
if(a.hour!=b.hour)
return a.hour>b.hour;
else if(a.minute!=b.minute)
return a.minute>b.minute;
else
return a.seconds>b.seconds;
}
int main()
{
int n,i;
cin>>n;
early.hour=24;
early.minute=60;
early.seconds=60;
late.hour=0;
late.minute=0;
late.seconds=0;
for(i=0;i<n;i++)
{
cin>>node.id;
scanf("%d:%d:%d",&node.hour,&node.minute,&node.seconds);
if(cmp(early,node))
early=node;
scanf("%d:%d:%d",&node.hour,&node.minute,&node.seconds);
if(cmp(node,late))
late=node;
}
cout<<early.id<<" "<<late.id;
return 0;
}
A 1036 Boys vs Girls
思路:
划水题~~
结构体存储,然后找结构体中分数最大值最小值,唯一需要注意的就是要判断男女。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//const int maxn = 10010;
struct pnode
{
string name;
char gender;
string id;
int score;
}node,low,high;
int main()
{
int n,i;
cin>>n;
high.score=-1;
low.score=101;
for(i=0;i<n;i++)
{
cin>>node.name>>node.gender>>node.id>>node.score;
if(node.gender=='F'&&node.score>high.score)
high=node;
if(node.gender=='M'&&node.score<low.score)
low=node;
}
int flag=0;
if(high.score==-1)
{
cout<<"Absent"<<endl;
flag=1;
}
else
cout<<high.name<<" "<<high.id<<endl;
if(low.score==101)
{
cout<<"Absent"<<endl;
flag=1;
}
else
cout<<low.name<<" "<<low.id<<endl;
if(flag==1)
cout<<"NA"<<endl;
else
cout<<high.score-low.score;
return 0;
}
A 1031 Hello World for U
思路:
这题感觉考数学,
n1=(len+2)/3;
n3=n1;
n2=len+2-n1-n3;
然后按照算出来的个数输出即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//const int maxn = 10010;
int main()
{
char str[110];
//cin.getline(str,110);
cin>>str;
int len=strlen(str);
int n1=(len+2)/3;
int n3=n1;
int n2=len+2-n1-n3;
int i,j;
for(i=0;i<n1-1;i++)
{
cout<<str[i];
for(j=0;j<n2-2;j++)
cout<<" ";
cout<<str[len-i-1]<<endl;
}
for(i=0;i<n2;i++)
{
cout<<str[n1+i-1];
}
return 0;
}
A 1019 General Palindromic Number
思路:
这题考点就是进制转换,然后就是字符串两端字符的对比
进制转换,可以记住下面的模板
int k=0;
int z[40];
do
{
z[k++]=n%b;
n=n/b;
}while(n!=0);
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<map>
using namespace std;
const int maxn=1000010;
int str[maxn];
bool judge(int z[],int num)
{
int i;
for(i=0;i<num/2;i++)
{
if(z[i]!=z[num-1-i])
return false;
}
return true;
}
int main()
{
int n,b,m,i,j,k=0;
cin>>n>>b;
int z[40];
do
{
z[k++]=n%b;
n=n/b;
}while(n!=0);
if(judge(z,k))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
for(i=k-1;i>=0;i--)
{
cout<<z[i];
if(i!=0)
cout<<" ";
}
}
A 1027 Colors in Mars
思路:
划水题~~
因为十进制范围在[0,168],所以不需要用上面模板,直接转换即可
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<map>
using namespace std;
//const int maxn=1000010;
//int str[maxn];
char a[13]={'0','1','2','3','4','5','6','7','8','9','A','B','C'};
int main()
{
int r,g,b;
cin>>r>>g>>b;
cout<<"#"<<a[r/13]<<a[r%13]<<a[g/13]<<a[g%13]<<a[b/13]<<a[b%13];
}
A 1058 A+B in Hogwarts
思路:
划水题~~
啰嗦了点,可能不够简洁,但是容易懂
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<map>
using namespace std;
//const int maxn=1000010;
//int str[maxn];
int main()
{
int g1,s1,k1,g2,s2,k2,g3,s3,k3;
scanf("%d.%d.%d",&g1,&s1,&k1);
scanf("%d.%d.%d",&g2,&s2,&k2);
int carry=0;
carry=(k1+k2)/29;
k3=(k1+k2)%29;
s3=(s1+s2+carry)%17;
carry=(s1+s2+carry)/17;
g3=g1+g2+carry;
printf("%d.%d.%d",g3,s3,k3);
return 0;
}
A 1001 A+B Format
思路:
数字转化成数组,其实和进制转换的模板是一样的
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
//const int maxn=1000010;
//int str[maxn];
int main()
{
int a,b,i;
cin>>a>>b;
int num[10];
int sum=a+b;
if(sum<0)
{
cout<<"-";
sum=-sum;
}
int len=0;
do
{
num[len++]=sum%10;
sum/=10;
}while(sum);
for(i=len-1;i>=0;i--)
{
cout<<num[i];
if(i>0&&i%3==0)
cout<<",";
}
return 0;
}
A 1005 Spell It Right
思路:
这题就是考整数与字符串之间的互相转换
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
//const int maxn=1000010;
//int str[maxn];
string s[10]={"zero","one","two","three","four","five","six","seven","eight","nine"};
int main()
{
char str[110];
cin>>str;
int len=strlen(str);
int sum=0;
int i;
for(i=0;i<len;i++)
{
int temp=str[i]-'0';
sum+=temp;
}
string c=to_string(sum);
for(i=0;i<c.length();i++)
{
cout<<s[c[i]-'0'];
if(i<c.length()-1)
cout<<" ";
}
return 0;
}
A 1035 Password
思路:
读入+比较,写程序最好培养一下模块化思想,既然每读入一行都要就行判断,那就写一个判断函数(代码整体会比较清晰)。由于要修改密码,所以传地址。
还有,要习惯一下vector变长数组的使用,用它来暂时存储后面需要的数据,相当于一个杂货篮。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
//const int maxn=1000010;
//int str[maxn];
struct person
{
char name[110];
char password[110];
}people;
bool judge(person & str)
{
int flag=0;
int len=strlen(str.password);
for(int i=0;i<len;i++)
{
if(str.password[i]=='1')
{
str.password[i]='@';
flag=1;
}
else if(str.password[i]=='0')
{
str.password[i]='%';
flag=1;
}
else if(str.password[i]=='l')
{
str.password[i]='L';
flag=1;
}
else if(str.password[i]=='O')
{
str.password[i]='o';
flag=1;
}
}
return flag;
}
int main()
{
int n;
cin>>n;
vector<person> ans;
int i;
for(i=0;i<n;i++)
{
cin>>people.name>>people.password;
if(judge(people))
ans.push_back(people);
}
if(ans.size()==0)
{
if(n==1)
printf("There is %d account and no account is modified",n);
else
printf("There are %d accounts and no account is modified",n);
}
else
{
cout<<ans.size()<<endl;
for(i=0;i<ans.size();i++)
{
cout<<ans[i].name<<" "<<ans[i].password<<endl;
}
}
return 0;
}
A 1077 Kuchiguse
思路:
(1)读入字符串数组(string型),翻转(转换成求最长前缀),同时比较得出最小字符串长度
(2)取第一个字符串的各个字符与其他字符串相同位置的字符进行比较,如果不相同,最长前缀到此为止(注意是取所有字符串的相同前缀,所有可以任取其中一个与其余的进行比较)
Tips:如果有样例测试不通过,可以考虑,是不是字符串数组取太小了
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
const int maxn=100010;
int main()
{
int n;
cin>>n;
getchar();//接受换行符
int i,j;
string str[maxn];
int minlen=maxn;
for(i=0;i<n;i++)
{
getline(cin,str[i]);
reverse(str[i].begin(),str[i].end());
if(minlen>str[i].size())
minlen=str[i].size();
}
int sum=0;
for(i=0;i<minlen;i++)
{
char c=str[0][i];
bool flag=true;
for(j=1;j<n;j++)
{
if(c!=str[j][i])
{
flag=false;
break;
}
}
if(flag)
sum++;
else
break;
}
if(sum)
{
for(i=sum-1;i>=0;i--)
{
cout<<str[0][i];
}
}
else
cout<<"nai";
return 0;
}
A 1082 Read Number in Chinese
思路:
这题感觉真的很难,很难想到周全
(1)首先定义两个指针,初始化指向两端,再四位四位移动,直到两个处在最高的四位节中(left指向当前需要输出的位,right指向与left同节的个位)
(2)处理额外多余的零,累积计算。(首位单独处理)
(3)四位移动,循环
细节点,代码注释都有
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include<iostream>
#include<string>
using namespace std;
//const int maxn=1000010;
string num[10]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
string wei[5]={"Shi","Bai","Qian","Wan","Yi"};
int main()
{
char str[15];
cin>>str;
int len=strlen(str);
int left=0;
int right=len-1;
if(str[0]=='-')
{
printf("Fu");
left++;
}
while(left+4<=right)
{
right-=4;//right每次左移四位,直到与left在同一节
}
while(left<len)
{
bool flag=false;//没有积累的0
bool isprint=0;//表示该节没有输出过其中的位
while(left<=right)//从左到右,处理数字中某节的每一位
{
if(left>0&&str[left]=='0')
flag=true;
else
{
if(flag==true)//存在积累的0
{
printf(" ling");
flag=false;
}
if(left>0)
printf(" ");//只要不是首位,后面的每一位前都要输出空格
cout<<num[str[left]-'0'];//输出当前数字
isprint=true;//该节至少有一位被输出
if(left!=right)//一节中除了个位外,都要输出十百千
{
cout<<" "<<wei[right-left-1];
}
}
left++;
}
if(isprint==true&&right!=len-1)//只要最后一小节,就得输出万亿
{
cout<<" "<<wei[(len-1-right)/4+2];
}
right+=4;
}
return 0;
}