PAT乙级题解

1001 害死人不偿命的(3n+1)猜想

传送门
知识点:简单模拟
思路:判断奇偶,根据题意即可
参考代码

点击查看代码
#include<iostream>
using namespace std;

int main()
{
    int n,cnt=0;
    cin>>n;
    while(n!=1){
        if(n%2)//奇数
            n=(3*n+1);
        n/=2;
        cnt++;
    }
    cout<<cnt<<endl;
    return 0;
}

1002 写出这个数

传送门
知识点:模拟,递归,映射
思路
输入数据过大,无法用int或long long存储,只能用string;
遍历string,ch-'0'即可得到该位数字,将各位数字相加得到sum,100位数字相加数据小于1000,使用int存储;
将sum拆分为数组,然后遍历输出映射的拼音,数字与拼音的映射使用string数组即可。
参考代码

点击查看代码
#include<iostream>
using namespace std;

string num[10]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
int cnt=0;
int a[110];

//将数x拆分为数组,递归
void fun(int x){
    if(x>=10)   fun(x/10);
    a[cnt++]=x%10;
}
int main()
{
    string st;
    int sum=0;
    cin>>st;
    //各位数字相加
    for(char ch:st)
        sum+=(ch-'0');
    fun(sum);
    //按位输出各数字映射的拼音
    for(int i=0;i<cnt;i++){
        cout<<num[a[i]];
        if(i!=cnt-1)    cout<<" ";
    }
    cout<<endl;
    return 0;
}

1003 我要通过!

传送么
知识点:模拟,找规律
思路
根据题意可以得出;
1、不含有PAT以外的字符;
2、P、T有且仅有一个;
3、字符串的格式为xPA..ATx..x,PT之间的A个数与T后面x的个数相等,而x也是由A组成的字符串,以cnt0、cnt1、cnt2表示其中A的个数,cnt0*cnt1==cnt2;
4、PT之间至少有一个A
参考代码

点击查看代码
#include<iostream>
using namespace std;

int main()
{
    int n;
    cin>>n;
    while(n--){
        string st;
        cin>>st;
        bool flag=true;
        int cnt=0;
        int cnt0=0,cnt1=0,cnt2=0;
        int cntp=0,cntt=0;
        for(char ch:st){
            if(ch=='P'){
                //记录P之前的A
                cnt0=cnt;
                cnt=0;
                cntp++;
            }
            else if(ch=='A')
                cnt++;
            else if(ch=='T'){
                //记录PT之间的A
                cnt1=cnt;
                cnt=0;
                cntt++;
            }
            //不能含有PAT以外的字符
            else    flag=false;
        }
        //记录T之后的A
        cnt2=cnt;
        //P、T有且仅有一个
        if(cntp!=1||cntt!=1)    flag=false;
        //PT之间至少有一个A,xPA..ATx..x
        if(cnt1==0||cnt1*cnt0!=cnt2) flag=false;
        if(flag==true)    cout<<"YES";
        else    cout<<"NO";
        if(n!=0)    cout<<endl;
    }
    return 0;
}

1004 成绩排名

传送门
知识点:结构体,排序
思路:使用结构体存储数据,使用sort以成绩为基准来排序,输出最高和最低成绩
参考代码

点击查看代码
#include<iostream>
#include<algorithm>
using namespace std;

//使用结构体存储数据
struct STU{
    int sorce;
    string num;
    string name;
};
STU stu[110];

bool cmp(STU A,STU B){
    return A.sorce<B.sorce;
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>stu[i].name>>stu[i].num>>stu[i].sorce;
    }
    //使用sort以成绩为基准来排序
    sort(stu,stu+n,cmp);
    //输出最高和最低成绩
    cout<<stu[n-1].name<<" "<<stu[n-1].num<<endl;
    cout<<stu[0].name<<" "<<stu[0].num<<endl;
    return 0;
}

1005 继续(3n+1)猜想

传送门
知识点:模拟,排序
思路:每个数x,经过一步步计算到达1,途中标记每一个中间量,表示他们被遍历过,可以由前面的数推算得到;剩下没有被标记过的就是关键数,从大到小排序后输出
参考代码

点击查看代码
#include<iostream>
#include<algorithm>
using namespace std;

int a[110],b[110];
bool v[110];

//从大到小排序
bool cmp(int a,int b){
    return a>b;
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        int x=a[i];
        while(x!=1){
            if(x%2) x=(3*x+1);
            x/=2;
            //数据范围为1~100
            if(x>100)   continue;
            //标记数字x被遍历
            v[x]=true;
        }
    }
    //将关键数存到到另一个数组,方便排序
    int cnt=0;
    for(int i=0;i<n;i++)
        if(v[a[i]]==false)
            b[cnt++]=a[i];
    sort(b,b+cnt,cmp);
    cout<<b[0];
    for(int i=1;i<cnt;i++)
        cout<<" "<<b[i];
    cout<<endl;
    return 0;
}

1006 换个格式输出整数

传送门
知识点:简单模拟
思路:分离百十个位上的数,按照题意输出
参考代码

点击查看代码
#include<iostream>
using namespace std;

int main()
{
    int n;
    cin>>n;
    //分离百十个上的数
    int b=n/100,s=(n/10)%10,g=n%10;
    for(int i=0;i<b;i++)
        cout<<"B";
    for(int i=0;i<s;i++)
        cout<<"S";
    for(int i=1;i<=g;i++)
        cout<<i;
    cout<<endl;
    return 0;
}

1007 素数对猜想

传送门
知识点:模拟
思路:遍历所有差为2的数对,判断两个数是否都是素数
参考代码

点击查看代码
#include<iostream>
using namespace std;

//判断素数
bool check(int x){
    for(int i=2;i*i<=x;i++)
        if(x%i==0)
            return false;
    return true;
}
int main()
{
    int n,cnt=0;
    cin>>n;
    for(int i=3;i<=n-2;i++)
        if(check(i)&&check(i+2))
            cnt++;
    cout<<cnt<<endl;
    return 0;
}

1008 数组元素循环右移问题

传送门
知识点:数组
思路:将数组整体翻转,再将前半和后半数组分别翻转,可以达到右移效果
参考代码

点击查看代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
    int n,m;
    cin>>n>>m;
    //移动所有数字相当没动
    m=m%n;
    vector<int> a(n);
    for(int i=0;i<n;i++)
        cin>>a[i];
    reverse(a.begin(),a.end());
    reverse(a.begin(),a.begin()+m);
    reverse(a.begin()+m,a.end());
    cout<<a[0];
    for(int i=1;i<n;i++)
        cout<<" "<<a[i];
    cout<<endl;
    return 0;
}

1009 说反话

传送门
知识点:字符串
思路:使用string数组存储数据,reverse将数组翻转
参考代码

点击查看代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;

int main()
{
    vector<string> words;
    string w;
    while(cin>>w)
        words.push_back(w);
    reverse(words.begin(),words.end());
    cout<<words[0];
    for(int i=1;i<words.size();i++)
        cout<<" "<<words[i];
    cout<<endl;
    return 0;
}

1010 一元多项式求导

传送门
知识点:模拟
思路:根据题意求导就行,注意零多项式
参考代码

点击查看代码
#include<iostream>
using namespace std;

int main()
{
    int m,n;
    cin>>m>>n;
    //特判零多项式
    if(n==0){
        puts("0 0");
        return 0;
    }
    if(m*n!=0)
        cout<<m*n<<" "<<n-1;
    while(cin>>m>>n){
        if(m*n!=0)
            cout<<" "<<m*n<<" "<<n-1;
    }
    return 0;
}

1011 A+B 和 C

传送门
知识点:数据范围
思路:int取值范围:-231~231-1;long long取值范围:-263~263-1
参考代码

点击查看代码
#include<iostream>
using namespace std;

int main()
{
    int T;
    cin>>T;
    for(int i=1;i<=T;i++){
        cout<<"Case #"<<i<<": ";
        long long a,b,c;
        cin>>a>>b>>c;
        if(a+b>c)
            puts("true");
        else    puts("false");
    }
    return 0;
}

1012 数字分类

传送门
知识点:模拟
思路:不难发现,将数字对5取模就得到了分类,使用switch-case语句来更清楚的表达多分支;由于A4为小数,需要特判
关键信息:若分类之后某一类不存在数字,则在相应位置输出 N。
参考代码

点击查看代码
#include<iostream>
#include<iomanip>
using namespace std;

int main()
{
    int n;
    cin>>n;
    int a[6]={0},cnt=0;
    bool flag=true,flag2=false;//表示加,表示A2这组没有数字
    for(int i=0;i<n;i++){
        int x;
        cin>>x;
        switch(x%5){
            case 0:
                if(x%2==0)  a[1]+=x;
                break;
            case 1:
                flag2=true;
                a[2]+=(flag?x:-x);
                flag=!flag;
                break;
            case 2:
                a[3]++;
                break;
            case 3:
                cnt++;
                a[4]+=x;
                break;
            case 4:
                a[5]=max(a[5],x);
                break;
        }
    }
    cout<<fixed<<setprecision(1);
    for(int i=1;i<=5;i++){
        int t=a[i];
        //A2的运算中有加有减,所以最终结果为0不能表示这类没有数字
        if((i!=2&&t==0)||(i==2&&flag2==false))
            cout<<"N";
        else{
            if(i==4)
                cout<<double(t)/cnt;
            else    cout<<t;
        }
        if(i!=5)    cout<<" ";
    }
    return 0;
}

1013 数素数

传送门
知识点:数学知识-素数
思路:先求出足够多的素数,然后输出;
参考代码

点击查看代码
#include<iostream>
#include<vector>
using namespace std;

bool check(int x){
    for(int i=2;i*i<=x;i++)
        if(x%i==0)
            return false;
    return true;
}
int main()
{
    vector<int> a;
    a.push_back(0);//让数组从1开始存储
    for(int i=2;i<2e5;i++)
        if(check(i))
            a.push_back(i);
    int m,n;
    cin>>m>>n;
    for(int i=m;i<=n;i++){
        cout<<a[i];
        if((i-m)%10==9)
            cout<<endl;
        else if(i!=n)   cout<<" ";
    }
    return 0;
}

1014 福尔摩斯的约会

传送门
知识点:模拟
思路
第一个条件:第一对相同的大写英文字母,以大写字母来代指星期,那么只有'A'~'G'是有效的
第二个条件:第一对相同的字符,24小时以'0''9'和'A''N'来代指
第三个条件:第一对相同英文字母,不区分大小写
参考代码

点击查看代码
#include<iostream>
using namespace std;

string d[7]={"MON","TUE","WED","THU","FRI","SAT","SUN"};

bool check0(char ch){//判断是否为大写字母
    return ch>='A'&&ch<='Z';
}
bool check1(char ch){//判断是否为数字
    return ch>='0'&&ch<='9';
}
bool check2(char ch){//判断是否为小写字母
    return ch>='a'&&ch<='z';
}
int main()
{
    string s0,s1,t0,t1;
    cin>>s0>>s1>>t0>>t1;
    bool flag=false;
    for(int i=0;i<s0.size()&&i<s1.size();i++){
        //第二个条件:第一对相同的字符
        if(flag&&s0[i]==s1[i]){
            if(check1(s0[i])){
                cout<<"0"<<s0[i]-'0'<<":";
                break;
            }
            else if(s0[i]>='A'&&s0[i]<='N'){
                cout<<s0[i]-'A'+10<<":";
                break;
            }
        }
        //第一个条件:第一对相同的大写英文字母
        if(s0[i]==s1[i]&&s0[i]>='A'&&s0[i]<='G'){
            cout<<d[s0[i]-'A']<<" ";
            flag=true;//表示开始判断第二对
        }
    }
    //第三个条件:第一对相同英文字母
    for(int i=0;i<t0.size()&&i<t1.size();i++){
        if(t0[i]==t1[i]&&(check0(t0[i])||check2(t1[i]))){
            if(i<10)
                cout<<"0"<<i;
            else    cout<<i;
            break;
        }
    }
    return 0;
}

1015 德才论

传送门
知识点:结构体排序
思路:根据题意来划分组;编写cmp函数用于排序,先以组别然后德分最后准考证据
参考代码

点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

struct STU{
    string num;//学号
    int x,y;//德分,才分
    int score;//总分
    int group;//组别
};
vector<STU> stu;

bool cmp(STU a,STU b){
    if(a.group!=b.group)
        return a.group<b.group;
    else if(a.score!=b.score)
        return a.score>b.score;
    else if(a.x!=b.x)
        return a.x>b.x;
    return a.num<b.num;
}
int main()
{
    int n,l,h;
    cin>>n>>l>>h;
    for(int i=0;i<n;i++){
        STU t;
        int g;
        cin>>t.num>>t.x>>t.y;
        if(t.x<l||t.y<l)    continue;
        if(t.x>=h&&t.y>=h)  g=1;
        else if(t.x>=h) g=2;
        else if(t.x>=t.y)   g=3;
        else    g=4;
        t.group=g;
        t.score=t.x+t.y;
        stu.push_back(t);
    }
    sort(stu.begin(),stu.end(),cmp);
    cout<<stu.size()<<endl;
    for(int i=0;i<stu.size();i++)
        cout<<stu[i].num<<" "<<stu[i].x<<" "<<stu[i].y<<endl;
    return 0;
}

1016 部分A+B

传送门
知识点:模拟
思路:遍历每一位数,记录目标数D出现次数cnt,根据目标数D和出现次数cnt构造P
参考代码

点击查看代码
#include<iostream>
using namespace std;

//记录d在x中的出现次数
int fun(int x,int d){
    int cnt=0;
    while(x>1){
        if(d==x%10) cnt++;
        x/=10;
    }
    return cnt;
}
//构造cnt位的x
int p(int x,int cnt){
    int ans=0;
    for(int i=0;i<cnt;i++)
        ans=ans*10+x;
    return ans;
}
int main()
{
    int a,da,b,db;
    cin>>a>>da>>b>>db;
    cout<<p(da,fun(a,da))+p(db,fun(b,db));
    return 0;
}

1017 A除以B

传送门
知识点:高精度
思路:高精度除法的模板题
参考代码

点击查看代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

vector<int> dev(vector<int> &A,int b,int &r){
    vector<int> C;
    for(int i=A.size()-1;i>=0;i--){
        r=r*10+A[i];
        C.push_back(r/b);
        r%=b;
    }
    //去除前导0
    reverse(C.begin(),C.end());
    while(C.size()>1&&C.back()==0)  C.pop_back();
    return C;
}
int main()
{
    string a;
    int b;
    vector<int> A;
    cin>>a>>b;
    //逆序输入、逆序输出,和其他高精度运算保持一致
    for(int i=a.size()-1;i>=0;i--)
        A.push_back(a[i]-'0');
    //余数
    int r=0;
    vector<int> q=dev(A,b,r);
    for(int i=q.size()-1;i>=0;i--)  cout<<q[i];
    cout<<" "<<r;
    return 0;
}

1018 锤子剪刀布

传送门
知识点:映射,模拟
思路:将字符和数字做映射,‘BCJ’映射为‘012’;平局两字符相等,相减为0;甲胜的情况BC、CJ、JB相减为-1、-1、2,加3模3后都为2;甲负即乙胜的情况为两字符相减后加3模3为1;在判断胜负的过程中记录每种字符胜利的次数
参考代码

点击查看代码
#include<iostream>
#include<map>
using namespace std;

map<char,int> h={{'B',0},{'C',1},{'J',2}};
char s[3]={'B','C','J'};
int j[3];//甲的胜、负、平
int x[3],y[3];//布,锤子,剪刀

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        char ch0,ch1;
        cin>>ch0>>ch1;
        int flag=(h[ch0]-h[ch1]+3)%3;
        j[flag]++;
        if(flag==2)//甲胜
            x[h[ch0]]++;
        else if(flag==1)//乙胜
            y[h[ch1]]++;
    }
    cout<<j[2]<<" "<<j[0]<<" "<<j[1]<<endl;
    cout<<j[1]<<" "<<j[0]<<" "<<j[2]<<endl;
    char J='B',Y='B';
    int num0=x[0],num1=y[0];
    for(int i=1;i<=2;i++)
        if(num0<x[i]){
            num0=x[i];
            J=s[i];
        }
    for(int i=1;i<=2;i++)
        if(num1<y[i]){
            num1=y[i];
            Y=s[i];
        }
    cout<<J<<" "<<Y;
    return 0;
}

1019 数字黑洞

传送门
知识点:模拟
思路
将输入的数字拆分为数组,排一次升序一次降序,再转化为数字,作相减操作,差作为下次循环的输入数字;
判断循环结束条件为差为0或者6174,当升序降序得到的数字相同时差为0,也意味着原来的数字各位相同;
注意不可以在开头判断输入为6174,因为当输入为6174时也应该走一遍这个过程即7641 - 1467 = 6174
参考代码

点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

//将数字转化为数组
vector<int> fun0(int n){
    vector<int> a;
    while(n>0){
        a.push_back(n%10);
        n/=10;
    }
    //加前导0
    if(a.size()<4){
        while(a.size()<4)
            a.push_back(0);
    }
    reverse(a.begin(),a.end());
    return a;
}
//将数组转化为数字
int fun1(vector<int> a){
    int res=0;
    for(int num:a)
        res=res*10+num;
    return res;
}
bool cmp(int a,int b){
    return a>b;
}
int main()
{
    int n;
    cin>>n;
    while(true){
        vector<int> x=fun0(n);
        sort(x.begin(),x.end(),cmp);
        int a=fun1(x);
        reverse(x.begin(),x.end());
        int b=fun1(x);
        n=a-b;
        printf("%04d - %04d = %04d\n",a,b,n);
        if(n==0||n==6174)   break;
    }
    return 0;
}

1020 月饼

传送门
知识点:结构体排序,贪心
思路:要想获取最大收益,那么在需求量固定的情况下,应该尽可能卖更贵即单价更高的;输入为总量和总价,算出单价,根据单价排降序
参考代码

点击查看代码
#include<iostream>
#include<algorithm>
using namespace std;

struct CAKE{
    double stock,sell,unit;
};
CAKE cake[1010];

bool cmp(CAKE a,CAKE b){
    return a.unit>b.unit;
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
        cin>>cake[i].stock;
    for(int i=0;i<n;i++){
        cin>>cake[i].sell;
        cake[i].unit=cake[i].sell/cake[i].stock;
    }
    //贪心法,按照单价来排序,优先选最贵的
    sort(cake,cake+n,cmp);
    double ans=0;
    for(int i=0;i<n;i++)
        if(m>=cake[i].stock){
            ans+=cake[i].sell;
            m-=cake[i].stock;
        }
        else{
            ans+=(m*cake[i].unit);
            break;
        }
    printf("%.2f\n",ans);
    return 0;
}

1021 个位数统计

传送门
知识点:模拟
思路:输入不超过1000的正整数,只能用string,遍历每一位记录数字出现的个数
参考代码

点击查看代码
#include<iostream>
using namespace std;

//记录每个数字的个数
int a[10];

int main()
{
    //位数<=1000;只能用string存储
    string st;
    cin>>st;
    for(char ch:st)
        a[ch-'0']++;
    for(int i=0;i<=9;i++)
        if(a[i]!=0)
            cout<<i<<":"<<a[i]<<endl;
    return 0;
}

1022 D进制的A+B

传送门
知识点:模拟,递归
思路:开始想的是进制转换,然后发现D进制的D如果很小的话,比如等于2,那么转换后的数字就没法用int存储了,只能用数组存储或者直接输出;显然边转换进制,边将每一位输出是方便的;在不知道数字的位数情况下,递归处理可以实现正着输出,或者先将每一位存在数组里再逆序输出
参考代码

点击查看代码
#include<iostream>
using namespace std;

//输出x的d进制数,递归实现正向输出
void fun(int x,int d){
    if(x<d){
        cout<<x;
        return;
    }
    fun(x/d,d);
    cout<<x%d;
}
int main()
{
    int a,b,d;
    cin>>a>>b>>d;
    fun(a+b,d);
    return 0;
}

1023 组个最小数

传送门
知识点:模拟,贪心
思路:找到最小的非0数字当首位,剩下的按照0~9顺序输出即可
参考代码

点击查看代码
#include<iostream>
using namespace std;

int a[10];

int main()
{
    for(int i=0;i<=9;i++)
        cin>>a[i];
    //找到最小的非0数字当首位
    int pre;
    for(int i=1;i<=9;i++)
        if(a[i]!=0){
            pre=i;
            a[i]--;
            break;
        }
    cout<<pre;
    for(int i=0;i<=9;i++)
        for(int j=0;j<a[i];j++)
            cout<<i;
    return 0;
}

1024 科学计数法

传送门
知识点:模拟
思路:使用string存储;由于整数部分固定为1位,那么第0位是符号位,第1位是整数部分,第2位是小数点,第3e-1位是小数部分,第e位是E,第e+1位是符号位,第e+2最后位是指数;找到E的位置,设为数字e,用来划分数字部分和指数部分;将指数部分的字符串转换为数字;根据指数符号位分类讨论,为正小数点往后挪,为负小数点往前挪
参考代码

点击查看代码
#include<iostream>
using namespace std;

int main()
{
    string st;
    cin>>st;
    if(st[0]=='-')
        cout<<'-';
    //找到E的位置
    int e=0;
    for(int i=4;i<st.size();i++)
        if(st[i]=='E'){
            e=i;
            break;
        }
    //确定指数
    int cnt=0;
    for(int i=e+2;i<st.size();i++)
        cnt=cnt*10+(st[i]-'0');
    if(st[e+1]=='+'){
        cout<<st[1];
        //e-3为小数部分的长度
        //小数点挪的超过小数部分的长度,则不需要小数点,并且还要后面补0
        if(cnt<e-3){
            for(int i=0;i<cnt;i++)
                cout<<st[i+3];
            cout<<".";
            for(int i=cnt+3;i<e;i++)
                cout<<st[i];
        }
        else{
            for(int i=3;i<e;i++)
                cout<<st[i];
            //输出多的零
            for(int i=0;i<cnt-e+3;i++)
                cout<<"0";
        }
    }
    else{
        if(cnt==0)
            for(int i=1;i<e;i++)
                cout<<st[i];
        else{
            cout<<"0.";
            for(int i=0;i<cnt-1;i++)
                cout<<"0";
            cout<<st[1];
            for(int i=3;i<e;i++)
                cout<<st[i];
        }
    }
    return 0;
}

1025 反转链表

传送门
知识点:链表,数组
思路:开始我是使用结构体搞链表的,但花里胡哨的搞不清楚了;后面我用vector来存储,使用reverse来反转也方便;开两个数组存储数据data和下一坐标next;输入是乱序的,需要按照起始点重新梳理一遍
参考代码

点击查看代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
using namespace std;

const int N=100010;
int ne[N],da[N];

int main()
{
    int st,n,k;
    cin>>st>>n>>k;
    for(int i=0;i<n;i++){
        int addr;
        cin>>addr;
        cin>>da[addr]>>ne[addr];
    }
    //输入是乱序的
    vector<int> list;
    for(int i=st;i!=-1;i=ne[i])
        list.push_back(i);
    for(int i=0;i+k<=list.size();i+=k)
        reverse(list.begin()+i,list.begin()+i+k);
    for(int i=0;i<list.size();i++){
        cout<<setw(5)<<setfill('0')<<list[i]<<' '<<da[list[i]]<<' ';
        if(i!=list.size()-1)
            cout<<setw(5)<<setfill('0')<<list[i+1]<<endl;
        else    puts("-1");
    }
    return 0;
}

1026 程序运行时间

传送门
知识点:模拟
思路:c2-c1得到时钟数,宰除以clk_tck得到运行时间;再转换为时分秒的形式,就是转换为60进制,注意四舍五入
参考代码

点击查看代码
#include<iostream>
#include<cstdio>
using namespace std;

const int CLK_TCK=100;

int main()
{
    int c1,c2;
    scanf("%d%d",&c1,&c2);
    int t=(c2-c1+50)/CLK_TCK;//四舍五入
    int s=t%60,m=(t/60)%60,h=t/3600;
    printf("%02d:%02d:%02d",h,m,s);
    return 0;
}

1027 打印沙漏

传送门
知识点:模拟、找规律
思路:找规律推公式得到,n阶沙漏的符号个数为2nn-1;首先判断沙漏的阶数,然后根据阶数和符号打印沙漏,先打印上班的倒三角,再打印下班的去了尖的三角
参考代码

点击查看代码
#include<iostream>
using namespace std;

void print(int n,char ch){
    //输出前n行的倒三角
    for(int i=0;i<n;i++){
        //输出空格
        for(int j=0;j<i;j++)
            cout<<" ";
        for(int j=0;j+2*i<2*n-1;j++)
            cout<<ch;
        cout<<endl;
    }
    for(int i=n-2;i>=0;i--){
        for(int j=0;j<i;j++)
            cout<<" ";
        for(int j=0;j+2*i<2*n-1;j++)
            cout<<ch;
        cout<<endl;
    }
}

int main()
{
    int n;
    char ch;
    cin>>n>>ch;
    for(int i=1;i<=30;i++)
        if(n<2*i*i-1){
            print(i-1,ch);
            cout<<n-2*(i-1)*(i-1)+1;
            break;
        }
    return 0;
}

1028 人口普查

传送门
知识点:结构体、排序、字符串
思路:首先生日以yyyy/mm/dd的格式输入,所以得要字符串转数字,将年月日信息提取出来;然后需要判断这些日期是否合理;将合理的数据放入数组中并排序;注意,当一个有效日期也没有的时候,需要输出0
参考代码

点击查看代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct BIR{
    string name;
    int y,m,d;
};
//返回年长的
bool cmp(BIR a,BIR b){
    if(a.y!=b.y)
        return a.y<b.y;
    else if(a.m!=b.m)
        return a.m<b.m;
    return a.d<b.d;
}
//判断日期是否合理
bool check(int y,int m,int d){
    if(y>2014||y<2014-200)
        return false;
    else if(y==2014&&m>9)
        return false;
    else if(y==2014-200&&m<9)
        return false;
    else if(y==2014&&m==9&&d>6)
        return false;
    else if(y==2014-200&&m==9&&d<6)
        return false;
    return true;
}
//将字符串拆分为数字
void fun(string t,int &y,int &m,int &d){
    int idx=0;
    for(int i=0;i<4;i++)
        y=y*10+(t[i+idx]-'0');
    idx=5;
    for(int i=0;i<2;i++)
        m=m*10+(t[i+idx]-'0');
    idx=8;
    for(int i=0;i<2;i++)
        d=d*10+(t[i+idx]-'0');
}
int main()
{
    vector<BIR> bir;
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        string name,t;
        cin>>name>>t;
        int y=0,m=0,d=0;
        fun(t,y,m,d);
        if(check(y,m,d))
            bir.push_back({name,y,m,d});
    }
    sort(bir.begin(),bir.end(),cmp);
    int cnt=bir.size();
    if(cnt!=0)
        cout<<cnt<<" "<<bir[0].name<<" "<<bir[cnt-1].name;
    //可能一个有效的日期都没有
    else    cout<<"0";
    return 0;
}

1029 旧键盘

传送门
知识点:字符串、映射
思路:开始的想法(有问题):双指针,i和j同时遍历两条字符串,若遍历到的字符相同则跳过,i和j都往后走一位,不相同则输出第一条字符串的字符,并标记该字符为已输出,i往后走一位,
由于ASCII码只有128个,所以可以开一个数组来记录键位是否损坏或者是否输出过;先遍历第二个字符串,将遍历到的字符标记为未损坏;再遍历第一个字符串,输出损坏的并且未被输出过的键位,并在输出后标记为已输出
参考代码

点击查看代码
#include<iostream>
using namespace std;

//ascii码总共128个
bool check[200];

int main()
{
    string s,t;
    cin>>s>>t;
    //先遍历字符串t,标记好的键位
    for(char ch:t){
        if(ch>='a'&&ch<='z')
            ch=char(ch-32);
        check[ch]=true;
    }
    for(char ch:s){
        if(ch>='a'&&ch<='z')
            ch=char(ch-32);
        if(check[ch]==false){
            cout<<ch;
            //标记已经输出过的键位
            check[ch]=true;
        }
    }
    return 0;
}

1030 完美数列

传送门
知识点:模拟、贪心、双指针
思路:开始的想法(有问题):双指针i和j,一前一后扫描数列,不符合条件则往里缩,贪心的选择缩的快的一边
首先将数列排序,快慢指针i和j,i和j之间的就是当前数列,i表示当前数列最小值,j向后扩张找到当前数列最大值
参考代码

点击查看代码
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int N=100010;
LL a[N];

int main()
{
    int n;
    LL p;
    cin>>n>>p;
    for(int i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    
    int cnt=0;
    for(int i=0;i<n;i++)
        //j向后扩张找到以a[i]为最小值的数列的最大值a[j],cnt为j-i+1
        for(int j=i+cnt;j<n;j++)
            if(a[i]*p>=a[j])
                cnt++;
            else    break;
    cout<<cnt;
    return 0;
}

1034 有理数四则运算

传送门
知识点:模拟、最大公约数
思路

  • 以分子分母的形式存储一个数,写个函数将这个数转化为题目要求的标准格式(负数要有括号、假分数形式--有整数部分和分数部分、当分母为0时输出Inf)
  • 然后就是以分数形式来处理两个数的加减乘除
  • 得到的也是分子分母的分数形式,再以标准格式输出
x=xa/xb;y=ya/yb;
加法:(xa*yb+xb*ya)/(ya*yb)
减法:(xa*yb-xb*ya)/(ya*yb)
乘法:(xa*ya)/(ya*yb)
除法:(xa*yb)/(ya*xb)

参考代码

点击查看代码
#include<iostream>
using namespace std;

typedef long long LL;
LL gcd(LL a, LL b)//求最大公约数
{
    return b ? gcd(b, a % b) : a;
}

void fun(LL a,LL b){
    if(b==0){
        cout<<"Inf";
        return;
    }
    bool flag=(a<0)^(b<0);//当只有一个小于0时,结果为true,是负数
    a=abs(a),b=abs(b);
    //约分一下,将分子和分母化为最简
    LL t=gcd(a,b);
    a/=t,b/=t;
    if(flag)    cout<<"(-";
    LL k=a/b;//k为整数部分
    a%=b;
    if(a==0){
        cout<<k;
    }
    else{
        if(k)    cout<<k<<" ";
        cout<<a<<"/"<<b;
    }
    if(flag)    cout<<")";
}

int main()
{
    LL xa,xb,ya,yb;
    char ch;//读入分号
    cin>>xa>>ch>>xb>>ya>>ch>>yb;
    //加法
    fun(xa,xb);
    cout<<" + ";
    fun(ya,yb);
    cout<<" = ";
    fun(xa*yb+xb*ya,xb*yb);
    cout<<endl;
    //减法
    fun(xa,xb);
    cout<<" - ";
    fun(ya,yb);
    cout<<" = ";
    fun(xa*yb-xb*ya,xb*yb);
    cout<<endl;
    //乘法
    fun(xa,xb);
    cout<<" * ";
    fun(ya,yb);
    cout<<" = ";
    fun(xa*ya,xb*yb);
    cout<<endl;
    //除法
    fun(xa,xb);
    cout<<" / ";
    fun(ya,yb);
    cout<<" = ";
    fun(xa*yb,xb*ya);
    cout<<endl;
    return 0;
}
posted @ 2023-02-07 17:09  林汐岚  阅读(76)  评论(0)    收藏  举报