PAT甲级--模拟

甲级题目较难,所以我分类,写了部分题目。
乙级题目的代码在我前一篇博文里,为了方便找,就把所有代码写在了一篇文章,没有写思路。
甲级题目我会尽力写点思路和注释,大家一起学习,供参考…
都在一个class文件写的,所以头文件基本不改动(偷个懒),不是都需要那么多头文件的

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=0int 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值