【PAT甲级真题整理二】1031~1060

目录

1031 Hello World for U(20)字符串处理

1032 Sharing(25)链表

1035 Password(20)模拟

1036 Boys vs Girls(25)排序

1037 Magic Coupon(25)排序

1038 Recover the Smallest Number(30)贪心

1039 Course List for Student(25)hash

1040 Longest Symmetric String(25)dp

1041 Be Unique(20)水题

1042 Shuffling Machine(20)模拟

1043 Is It a Binary Search Tree(25)二叉查找树

*1044 Shopping in Mars(25)模拟

1046 Shortest Distance(20)模拟

1047 Student List for Course(25)hash

1048 Find Coins(25)模拟

1050 String Subtraction(20)字符串处理,水

1051 Pop Sequence(25)栈的简单应用

1052 Linked List Sorting(25)模拟链表

1054 The Dominant Color(20)map的简单应用

1055 The World's Richest(25)排序

1056 Mice and Rice(25)队列的应用

1058 A+B in Hogwarts(20)模拟

1059 Prime Factors(25)线性素数筛


1031 Hello World for U(20)字符串处理

【题意】

将一个字符串用U字形显示,若n为字符串的长度。

【解题思路】

行:(n+2)/3,列:n+2-2*行

开一个二维数组存储字符比较方便。

【代码】

#include<bits/stdc++.h>
using namespace std;
int main()
{
    char s[100];
    char a[40][40];
    scanf("%s",s);
    int i,j;
    int n1,n2;
    int len=strlen(s);
    n1=(len+2)/3;
    n2=(len+2-n1-n1);
    for(i=1;i<=n1;i++)
    {
        for(j=1;j<=n2;j++)
            a[i][j]=' ';
    }
    int q=0;
    for(i=1;i<=n1;i++)
        a[i][1]=s[q++];
    for(i=2;i<=n2;i++)
        a[n1][i]=s[q++];
    for(i=n1-1;i>=1;i--)
        a[i][n2]=s[q++];
    for(i=1;i<=n1;i++)
    {
        for(j=1;j<=n2;j++)
            printf("%c",a[i][j]);
        printf("\n");
    }
    return 0;
}

 

1032 Sharing(25)链表

【题意】

给两个单词的初始字母的节点地址,再给n个节点,每个节点由地址,字符,和指向下一个字符的地址构成,输出两个单词相同的字母的那个节点的地址。

【解题思路】

这里不用链表做,链表真是代码太长了,直接用结构存储就可以了,为了方便再定义一个vis数组,将第一个单词出现过的字母的地址都记为1,等到遍历第二个单词的时候,一旦vis数组=1,即说明这个字母和上一个单词重复了。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int vis[maxn];
struct letter
{
    int st,en;
    char a;
}l[maxn];
int main()
{
    int a,b,a2,b2,n,x,t,flag=0;
    char c;
    memset(vis,0,sizeof(vis));
    scanf("%d%d%d",&a,&b,&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d %c %d",&a2,&c,&b2);
        l[a2].st=a2;
        l[a2].en=b2;
        l[a2].a=c;
    }
    x=a;
    while(x!=-1)
    {
        vis[x]=1;
        x=l[x].en;
    }
    x=b;
    while(x!=-1)
    {
        if(vis[x])
        {
            t=x;
            flag=1;
            break;
        }
        x=l[x].en;
    }
    if(flag)printf("%05d\n",t);
    else printf("-1\n");
    return 0;
}

 

1035 Password(20)模拟

【题意】

给n个用户名和密码,把密码中的1改为@,0改为%,l改为L,O改为o。让你输出需要修改密码的用户名个数,以及对应的用户名和密码,按输入的顺序。如果没有用户需要修改,则输出对应的语句,注意单复数。

【解题思路】

水题没啥好说的,注意单复数!!不然一直会有1个测试点过不了。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
struct user
{
    char a[25],b[25];
    int f=0;
}u[maxn];
int main()
{
    int n,num=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s %s",&u[i].a,&u[i].b);
        int l=strlen(u[i].b);
        int flag=0;
        for(int j=0;j<l;j++)
        {
            if(u[i].b[j]=='1')
            {
                u[i].b[j]='@';
                flag++;
            }
            else if(u[i].b[j]=='0')
            {
                u[i].b[j]='%';
                flag++;
            }
            else if(u[i].b[j]=='O')
            {
                u[i].b[j]='o';
                flag++;
            }
            else if(u[i].b[j]=='l')
            {
                u[i].b[j]='L';
                flag++;
            }
        }
        if(flag!=0)
        {
            num++;
            u[i].f=1;
        }
    }
    if(!num && n>1)printf("There are %d accounts and no account is modified\n",n);
    else if(!num && n==1)printf("There is %d account and no account is modified\n",n);
    else
    {
        printf("%d\n",num);
        for(int i=0;i<n;i++)
        {
            if(u[i].f)
                printf("%s %s\n",u[i].a,u[i].b);
        }
    }
    return 0;
}

 

1036 Boys vs Girls(25)排序

【题意】

给n个学生,输出男生中成绩最低的人的名字和学号,输出女生中成绩最高的人的名字和学号,并输出成绩的差值。若没有男生或没有女生,在那一栏输出“Absent”,成绩的差值输出"NA"。

【解题思路】

排序即可,注意细节。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
struct people
{
    char name[15];
    char sno[15];
    int score;
}a[maxn],b[maxn];
bool cmp(people a,people b)
{
    return a.score<b.score;
}
int main()
{
    char c;
    int n,k1=0,k2=0;
    scanf("%d",&n);
    while(n--)
    {
        char s[15];
        scanf("%s %c",s,&c);
        if(c=='M')
        {
            strcpy(a[k1].name,s);
            scanf("%s %d",a[k1].sno,&a[k1].score);
            //printf("%s %s %d\n",a[k1].name,a[k1].sno,a[k1].score);
            k1++;
        }
        else
        {
            strcpy(b[k2].name,s);
            scanf("%s %d",b[k2].sno,&b[k2].score);
            k2++;
        }
    }
    sort(a,a+k1,cmp);
    sort(b,b+k2,cmp);
    if(k2==0)
    {
        printf("Absent\n");
        printf("%s %s\n",a[0].name,a[0].sno);
        printf("NA\n");
    }
    else if(k1==0)
    {
        printf("%s %s\n",b[k2-1].name,b[k2-1].sno);
        printf("Absent\n");
        printf("NA\n");
    }
    else
    {
        printf("%s %s\n",b[k2-1].name,b[k2-1].sno);
        printf("%s %s\n",a[0].name,a[0].sno);
        printf("%d\n",b[k2-1].score-a[0].score);

    }
    return 0;

}

 

1037 Magic Coupon(25)排序

【题意】

题目说了那么多,就是给你两个序列,分别选取元素进行一对一相乘,求得到的最大乘积。

【解题思路】

将两个序列的正和负数分开,排个序,负数从小到大排,正数从大到小排,然后分别相乘就可以了。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],b[maxn],c[maxn],d[maxn];
bool cmp(int a ,int b)
{
    return a>b;
}
int main()
{
    int n,k1=0,k2=0,j1=0,j2=0,ans=0;
    scanf("%d",&n);
    while(n--)
    {
        int x;
        scanf("%d",&x);
        if(x>=0)a[k1++]=x;
        else b[k2++]=x;
    }
     scanf("%d",&n);
     while(n--)
     {
        int x;
        scanf("%d",&x);
        if(x>=0)c[j1++]=x;
        else d[j2++]=x;
     }
    sort(a,a+k1,cmp);sort(c,c+j1,cmp);
    sort(b,b+k2);sort(d,d+j2);
    for(int i=0;i<k1 && i<j1;i++)
        ans+=a[i]*c[i];
    for(int i=0;i<k2 && i<j2;i++)
        ans+=b[i]*d[i];
    printf("%d\n",ans);
    return 0;
}

1038 Recover the Smallest Number(30)贪心

【题意】

给n个数字,将其组合成一个最小的数。

【解题思路】

用字符串记录数字即可,想要组合成的数最小,不是按照字典序排列就可以的,必须保证两个字符串构成的数字是最小的才行,所以cmp函数写成return a + b < b + a的形式,保证它排列按照能够组成的最小数字的形式排列。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int INF=9999999999;
string s[maxn];
bool cmp(string a,string b)
{
    return a+b<b+a;
}
int main()
{
    int n,index=INF;
    scanf("%d",&n);
    string str="";
    for(int i=0;i<n;i++)
        cin>>s[i];
    sort(s,s+n,cmp);
    for(int i=0;i<n;i++)
        str=str+s[i];
    for(int i=0;i<str.size();i++)
    {
        if(str[i]!='0')
        {
            index=i;
            break;
        }
    }
    for(int i=index;i<str.size();i++)
        printf("%c",str[i]);
    if(str.size()==0 || index==INF)printf("0");
    printf("\n");
    return 0;
}

1039 Course List for Student(25)hash

【题意】

有N个学生,K门课,给出选择每门课的学生姓名,最后对于给出的N个学生的姓名的选课情况进行询问,要求按顺序给出每个学生的选课情况。

【解题思路】

这题如果用string保存学生的姓名会有一个测试点超时,所以需要用到hash将学生的姓名变为Int型。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=26*26*26*10+10;
struct student
{
    int name;
    set<int>se;
    int cnt=0;
}s[maxn];
map<int,int>mp;
int main()
{
    int n,m,k=0;
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int x,n2;
        scanf("%d%d",&x,&n2);
        while(n2--)
        {
            char str[5];
            int sum=0;
            scanf("%s",str);
            for(int i=0;i<3;i++)
                sum=sum*26+str[i]-'A';
            sum=sum*10+str[3]-'0';
            if(!mp.count(sum))
            {
                s[k].name=sum;
                s[k].se.insert(x);
                s[k].cnt++;
                mp[sum]=k++;
            }
            else
            {
                s[mp[sum]].se.insert(x);
                s[mp[sum]].cnt++;
            }
        }
    }
    while(n--)
    {
        char str[5];
        scanf("%s",str);
        printf("%s ",str);
        int sum=0;
        for(int i=0;i<3;i++)
            sum=sum*26+str[i]-'A';
        sum=sum*10+str[3]-'0';
        if(mp.count(sum))printf("%d",s[mp[sum]].cnt);
        else
        {
            printf("0\n");
            continue;
        }
        set<int>::iterator it;
        for (it=s[mp[sum]].se.begin();it!=s[mp[sum]].se.end();it++){
            printf(" %d", *it);
        }
        printf("\n");
    }
    return 0;
}

1040 Longest Symmetric String(25)dp

【题意】

求最长回文串。

【解题思路】

其实我觉得这题数据小不用dp也能做……但是直接暴力我有个测试点老过不去。

dp思路来自柳神:https://www.liuchuo.net/archives/2104

dp[i][j]表示s[i]到s[j]所表示的字串是否是回文字串。只有0和1,递推方程为:

  • 当s[i] == s[j] : dp[i][j] = dp[i+1][j-1]
  • 当s[i] != s[j] : dp[i][j] =0
  • 边界:dp[i][i] = 1, dp[i][i+1] = (s[i] == s[i+1]) ? 1 : 0 

因为i、j如果从小到大的顺序来枚举的话,无法保证更新dp[i][j]的时候dp[i+1][j-1]已经被计算过。因此不妨考虑按照字串的长度和子串的初试位置进行枚举,即第一遍将长度为3的子串的dp的值全部求出,第二遍通过第一遍结果计算出长度为4的子串的dp的值…这样就可以避免状态无法转移的问题。

首先初始化dp[i][i] = 1, dp[i][i+1],把长度为1和2的都初始化好,然后从L = 3开始一直到 L <= len 根据动态规划的递归方程来判断

【代码】

#include<bits/stdc++.h>
using namespace std;
int dp[1005][1005];
int main()
{
    string s;
    getline(cin,s);
    int len=s.size(),ans=1;
    for(int i=0;i<len;i++)
    {
        dp[i][i]=1;
        if(i+1<len && s[i]==s[i+1])
        {
            dp[i][i+1]=1;
            ans=2;
        }
    }
    for(int i=3;i<=len;i++)
    {
        for(int j=0;j+i-1<len;j++)
        {
            int k=j+i-1;
            if(s[j]==s[k] && dp[j+1][k-1])
            {
                dp[j][k]=1;
                ans=i;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

1041 Be Unique(20)水题

【题意】

给n个数,输出第一个只出现一次的数,没有则输出None。

【解题思路】

水题,注意细节。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+5;
int a[maxn];
int cnt[maxn];
int main()
{
    int n;
    memset(cnt,0,sizeof(cnt));
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        cnt[a[i]]++;
    }
    int ans=-1;
    for(int i=0;i<n;i++){
        if(cnt[a[i]]==1){
            ans=a[i];
            break;
        }
    }
    if(ans==-1)
        printf("None\n");
    else
        printf("%d\n",ans);
    return 0;
}

 

1042 Shuffling Machine(20)模拟

【题意】

给n表示洗牌的次数,再给一个大小为54的序列a[],a[i]表示把第i张牌放到第a[i]个位置,最后输出洗n次牌之后牌的序列。

【解题思路】

水题,注意细节。

【代码】

#include<bits/stdc++.h>
using namespace std;
string s[55]={"0","S1","S2","S3","S4","S5","S6","S7","S8","S9","S10","S11","S12","S13",
              "H1","H2","H3","H4","H5","H6","H7","H8","H9","H10","H11","H12","H13",
              "C1","C2","C3","C4","C5","C6","C7","C8","C9","C10","C11","C12","C13",
              "D1","D2","D3","D4","D5","D6","D7","D8","D9","D10","D11","D12","D13",
              "J1","J2"};
string s2[55];
int a[55];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=54;i++)
        scanf("%d",&a[i]);
    while(n--)
    {
        for(int i=1;i<=54;i++)
            s2[a[i]]=s[i];
        for(int i=1;i<=54;i++)
            s[i]=s2[i];
    }
    cout<<s[1];
    for(int i=2;i<=54;i++)
        cout<<" "<<s[i];
    printf("\n");
    return 0;
}

 

1043 Is It a Binary Search Tree(25)二叉查找树

【题意】

给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。

【解题思路】

模板题。不过这题里可以插入重复节点,在二叉查找树里会将重复节点插入与它同值节点的右子树中,在镜像二叉树中会将重复节点插入与它同值节点的左子树中。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int pre[maxn],post[maxn],a[maxn],cnt1=0,cnt2=0;
typedef struct Node
{
    int val;
    struct Node *left,*right;
}Node,*BNode;
BNode insertnode(BNode root,int x)
{
    if(root==NULL)
    {
        root=new Node();
        root->left=root->right=NULL;
        root->val=x;
        return root;
    }
    else if(x<root->val)
        root->left=insertnode(root->left,x);
    else if(x>=root->val)
        root->right=insertnode(root->right,x);
    return root;
}
BNode insertnode2(BNode root,int x)
{
    if(root==NULL)
    {
        root=new Node();
        root->left=root->right=NULL;
        root->val=x;
        return root;
    }
    else if(x>=root->val)
        root->left=insertnode2(root->left,x);
    else if(x<root->val)
        root->right=insertnode2(root->right,x);
    return root;
}
void preorder(BNode root)
{
    if(root==NULL)return;
    pre[cnt1++]=root->val;
    preorder(root->left);
    preorder(root->right);
}
void postorder(BNode root)
{
    if(root==NULL)return;
    postorder(root->left);
    postorder(root->right);
    post[cnt2++]=root->val;
}
int main()
{
    int n,flag=1,flag2=1;
    BNode root=NULL;
    BNode root2=NULL;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        root=insertnode(root,a[i]);
        root2=insertnode2(root2,a[i]);
    }
    preorder(root);
    for(int i=0;i<n;i++)
    {
        if(a[i]!=pre[i])
        {
            flag=0;
            break;
        }
    }
    if(flag)postorder(root);
    else
    {
        cnt1=cnt2=0;
        preorder(root2);
        for(int i=0;i<n;i++)
        {
            if(a[i]!=pre[i])
            {
                flag2=0;
                break;
            }
        }
        if(flag2)postorder(root2);
    }
    if(flag || flag2)
    {
        printf("YES\n%d",post[0]);
        for(int i=1;i<n;i++)
            printf(" %d",post[i]);
        printf("\n");
    }
    else printf("NO\n");
    return 0;
}

*1044 Shopping in Mars(25)模拟

【题意】

给出n个数,求所有存在的区间[l,r],使得a[l]~a[r]的和为m,并且按l的大小顺序输出对应区间。如果不存在和为m的区间段,则输出a[l]~a[r]-m最小的区间段方案。

【解题思路】

定义start为区间起始位置,i为区间结束位置,sum为区间和,当sum<m时i继续向后移,当sum>=m时,因为考虑到这组数里可能并没有一个区间可以等于m,需要计算a[l]~a[r]-m最小的区间段,所以加一个sum-m<=limit的判断,如果sum-m<limit,说明该数组里有更小的a[l]~a[r]-m满足答案,则将之前记录的答案全部清空,并将limit=sum-m。当sum>=m时,也意味着i不用再向后移了,所以为了减小sum,应该将start向后移一位,并将i向前移一位,继续循环。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int INF=2147483647;
const int maxn=1e5+5;
int a[maxn];
struct Ans
{
    int i,j;
}A;
vector<Ans>ans;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int start=1,limit=INF,sum=0;
    for(int i=1;i<=n;i++)
    {
        sum+=a[i];
        if(sum<m)
            continue;
        if(sum-m<=limit)
        {
            if(sum-m<limit)
            {
                ans.clear();
                limit=sum-m;
            }
            A.i=start;
            A.j=i;
            ans.push_back(A);
        }
        if(sum>=m && start<i)
        {
            sum-=a[i];
            i--;
            sum-=a[start];
            start++;
        }
    }
    for(int i=0;i<ans.size();i++)
        printf("%d-%d\n",ans[i].i,ans[i].j);
    return 0;
}

 

1046 Shortest Distance(20)模拟

【题意】

给一个环,求环上两点的最短路。

【解题思路】

由题意可知最短路肯定只有两种可能,要么顺时针要么逆时针,但直接暴力最后一个测试点会超时,那么就该想到建一个数组保存前缀和,两段最短路就等于x=sum[v-1]-sum[u-1],y=sum[n]-x,只要取两者的最小值即可。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],sum[maxn]={0};
int main()
{
    int n,m;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    scanf("%d",&m);
    while(m--)
    {
        int u,v,sum1=0,sum2=0;
        scanf("%d%d",&u,&v);
        if(u>v)swap(u,v);
        sum1=sum[v-1]-sum[u-1];
        sum2=sum[n]-sum1;
        printf("%d\n",min(sum1,sum2));
    }
    return 0;
}

1047 Student List for Course(25)hash

【题意】

给出选课人数和课程数目,然后再给出每个人的选课情况,请针对每门课程输出选课人数以及所有选该课的学生姓名,按照字典序。

【解题思路】

这题和之前那题很像,因为cin会超时所以这里还是用了hash,也可以更简单地直接用scanf的字符串,然后字符串排序来做。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=2505;
vector<int>s[maxn];
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    while(n--)
    {
        char s1[5];
        int m,sum=0;
        scanf("%s%d",s1,&m);
        for(int i=0;i<3;i++)
            sum=sum*26+s1[i]-'A';
        sum=sum*10+s1[3]-'0';
        while(m--)
        {
            int x;
            scanf("%d",&x);
            s[x].push_back(sum);
        }
    }
    for(int i=1;i<=k;i++)
    {
        priority_queue<int,vector<int>,greater<int> >q;
        printf("%d %d\n",i,s[i].size());
        for(int j=0;j<s[i].size();j++)
            q.push(s[i][j]);
        while(!q.empty())
        {
            char s2[5];
            int t=q.top(),i=3,j=2;
            s2[4]='\0';
            s2[3]=t%10+'0';
            t/=10;
            while(i--)
            {
                int x=t%26;
                s2[j--]=x+'A';
                t/=26;
            }
            printf("%s\n",s2);
            q.pop();
        }
    }
    return 0;
}

1048 Find Coins(25)模拟

【题意】

给n个数,在其中找到两个数a,b刚好等于m,若方案不只一种则输出最小的a,若不存在则输出No solution。

【解题思路】

因为当方案不只一种时要输出最小的a所以需要将a[n]数组排序,设置两个指针,一个指向a[0],一个指向a[n-1],当这两个数相加小于m时,start++,大于m时,end--,等于m时直接跳出循环即可。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    int start=0,end=n-1;
    sort(a,a+n);
    while(start<end)
    {
        int sum=a[start]+a[end];
        if(sum==m)break;
        else if(sum<m)start++;
        else end--;
    }
    if(start>=end)printf("No Solution\n");
    else printf("%d %d\n",a[start],a[end]);
    return 0;
}

 

1050 String Subtraction(20)字符串处理,水

【题意】

给两个字符串s1和s2,将s1删去s2中出现的字符后输出s1。

【解题思路】

因为PAT不支持gets输入所以这里用cin.get(),只需记录s2中出现的字符,当s1中的字符在记录数组中存在时不输出,反之输出。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
char s1[maxn],s2[maxn];
int vis[maxn];
int main()
{
    cin.get(s1,maxn);
    getchar();
    cin.get(s2,maxn);
    memset(vis,0,sizeof(vis));
    for(int i=0;i<strlen(s2);i++)
        vis[s2[i]]=1;
    for(int i=0;i<strlen(s1);i++)
    {
        int x=s1[i];
        if(!vis[x])printf("%c",s1[i]);
    }
    printf("\n");
    return 0;
}

 

1051 Pop Sequence(25)栈的简单应用

【题意】

给定m,n,k,m为栈的最大容量,将n个数1,2,3...,n按顺序压入栈中,看以下m组出栈序列是否符合。

【解题思路】

设定一个数组vis记录已经压入过栈中的元素,当栈为空或者栈顶元素不等于出栈元素时,继续压入还没被压入栈中的元素,若栈的容量大于m时直接跳出循环,否则直到压入出栈元素为止,再将该元素弹出。若栈顶元素等于出栈元素时直接弹出。当最后栈为空且flag=1时输出YES,反之输出NO。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int vis[maxn],a[maxn];
int main()
{
    int m,n,k;
    scanf("%d%d%d",&m,&n,&k);
    while(k--)
    {
        int flag=1;
        memset(vis,0,sizeof(vis));
        stack<int>s;
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
        {
            if(s.empty() || (!s.empty() &&s.top()!=a[i]))
            {
                for(int j=1;j<=a[i];j++)
                {
                    if(!vis[j])s.push(j);
                    vis[j]=1;
                    if(s.size()>m)
                    {
                        flag=0;
                        break;
                    }
                }
                if(s.top()==a[i])s.pop();
            }
            else s.pop();
            if(!flag)break;
        }
        if(flag && s.empty())
            printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

1052 Linked List Sorting(25)模拟链表

【题意】

给出链表的结点个数和头结点的地址,将以该头结点为起点的链表按照值从小到大重新组合成一个新链表,注意这里给出的结点个数不一定都在链表里。

【解题思路】

用数组模拟链表,注意细节。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
struct Node
{
    int head;
    int key;
    int next;
}a[maxn],node[maxn];
bool cmp(Node a,Node b)
{
    return a.key<b.key;
}
int main()
{
    int n,x,cnt=0;
    scanf("%d%d",&n,&x);
    for(int i=0;i<n;i++)
    {
        int b,c,d;
        scanf("%d%d%d",&b,&c,&d);
        a[b].head=b;
        a[b].key=c;
        a[b].next=d;
    }
    while(x!=-1)
    {
        node[cnt].head=a[x].head;
        node[cnt].key=a[x].key;
        node[cnt].next=a[x].next;
        x=a[x].next;
        cnt++;
    }
    sort(node,node+cnt,cmp);
    if(cnt==0)//最后一个测试点
    {
        printf("0 -1\n");
        return 0;
    }
    printf("%d %05d\n",cnt,node[0].head);
    for(int i=0;i<cnt;i++)
    {
        printf("%05d %d ",node[i].head,node[i].key);
        if(i==cnt-1)printf("-1\n");
        else printf("%05d\n",node[i+1].head);
    }
    return 0;
}

 

1054 The Dominant Color(20)map的简单应用

【题意】

输出一幅图中像素值出现过半的像素。

【解题思路】

用map来记录该像素值是否出现过,若没出现过,map的关键字则对应该像素,map的值则对应该像素的索引。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],b[maxn];
int main()
{
    int N,M,cnt=0;
    memset(a,0,sizeof(a));
    scanf("%d%d",&N,&M);
    int sum=N*M;
    map<int,int>m;
    for(int i=0;i<sum;i++)
    {
        int x;
        scanf("%d",&x);
        if(!m.count(x))
        {
            b[cnt]=x;
            m[x]=cnt++;
            a[m[x]]++;
        }
        else a[m[x]]++;
    }
    for(int i=0;i<cnt;i++)
    {
        if(a[i]>=sum/2)
        {
            printf("%d\n",b[i]);
            break;
        }
    }
    return 0;
}

 

1055 The World's Richest(25)排序

【题意】

给出n个人的姓名、年龄和拥有的钱,然后进行k次查询,输出年龄在[amin,amx]内的前m个最富有的人的信息。如果财富值相同就就先输出年龄小的,如果年龄相同就按照名字的字典序排序输出。

【解题思路】

将n个人按照财富从大到小排序,若财富相同则按照年龄从小到大排,若年龄相同则按照名字从小到大排,只要符合所给年龄范围内则输出该人的名字、年龄、财富,cnt++,若cnt=0时则说明没有人符合,则输出None。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
struct people
{
    char s[10];
    int age;
    int worth;
}p[maxn];
bool cmp(people a,people b)
{
    if(a.worth!=b.worth)
        return a.worth>b.worth;
    else
    {
        if(a.age!=b.age)
            return a.age<b.age;
        else
            return strcmp(a.s,b.s)<0;
    }
}
int main()
{
    int n,k,m;
    scanf("%d%d",&n,&m);
    getchar();
    for(int i=0;i<n;i++)
        scanf("%s%d%d",p[i].s,&p[i].age,&p[i].worth);
    sort(p,p+n,cmp);
    for(int i=1;i<=m;i++)
    {
        int num,a1,a2,cnt=0;
        scanf("%d%d%d",&num,&a1,&a2);
        printf("Case #%d:\n",i);
        for(int i=0;i<n;i++)
        {
            if(p[i].age>=a1 && p[i].age<=a2)
            {
                cnt++;
                printf("%s %d %d\n",p[i].s,p[i].age,p[i].worth);
            }
            if(cnt==num)break;
        }
        if(!cnt)printf("None\n");
    }
    return 0;
}

 

1056 Mice and Rice(25)队列的应用

【题意】

有n只老鼠每m只分成1组比赛,每组重量最大者胜出,将胜出的小组再每m只分成1组继续比赛,直到每个老鼠都要一个名次。

【解题思路】

简单模拟后可得将所有老鼠的编号都进入队列中,将每m只分成1组比赛,每比一只则将其出队,并更新重量最大的老鼠的编号,将其入队进行下一轮的比赛。每一轮的名次即为该轮组数+1。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
struct Mice
{
    int weight,rank;
}mice[maxn];
int main()
{
    queue<int>q;
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        scanf("%d",&mice[i].weight);
    for(int i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        q.push(x);
    }
    int sum=n,x;
    while(q.size()!=1)
    {
        if(sum%m)x=sum/m+1;
        else x=sum/m;
        for(int i=0;i<x;i++)//老鼠的组数
        {
            int max1=q.front();
            for(int j=0;j<m;j++)//每m只老鼠一组
            {
                if(i*m+j>=sum)break;
                int t=q.front();
                if(mice[t].weight>mice[max1].weight)
                    max1=t;
                mice[t].rank=x+1;
                q.pop();
            }
            q.push(max1);//将胜出的老鼠的编号进入队列
        }
        sum=x;//下一轮比赛老鼠的总数=上一轮比赛的组数
    }
    mice[q.front()].rank=1;
    printf("%d",mice[0].rank);
    for(int i=1;i<n;i++)
        printf(" %d",mice[i].rank);
    printf("\n");
    return 0;
}

 

1058 A+B in Hogwarts(20)模拟

【题意】

计算Galleon.Sickle.Knut+Galleon.Sickle.Knut,Knut位满29进1,Sickle位满17进1。

【解题思路】

水题,注意细节。

【代码】

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a1,a2,b1,b2,c1,c2;
    scanf("%d.%d.%d",&a1,&b1,&c1);
    scanf("%d.%d.%d",&a2,&b2,&c2);
    int a3,b3,c3,t1=0,t2=0;
    c3=(c1+c2)%29;
    t1=(c1+c2)/29;
    b3=(b1+b2+t1)%17;
    t2=(b1+b2+t1)/17;
    a3=a1+a2+t2;
    printf("%d.%d.%d\n",a3,b3,c3);
    return 0;
}

 

1059 Prime Factors(25)线性素数筛

【题意】

将一个数质因数分解,若因子相同时要写成几次方的形式。

【解题思路】

long int其实就是int,所以按照Int的范围开方之后不会超过60000,那么素数筛的上限就去60000就好了,然后要注意当n=1时,输出1=1,不然会有一个测试点过不了。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=6e4+5;
int prime[maxn],vis[maxn],cnt=0;
void isprime()
{
    for(int i=2;i<maxn;i++)
    {
        if(!vis[i])prime[cnt++]=i;
        for(int j=0;j<cnt && i*prime[j]<maxn;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}
vector<pair<int,int> >v;
int main()
{
    int n;
    isprime();
    scanf("%d",&n);
    if(n==1)
    {
        printf("1=1\n");
        return 0;
    }
    printf("%d=",n);
    for(int i=0;i<cnt && n!=1;i++)
    {
        int t=0;
        while(n%prime[i]==0)
        {
            n/=prime[i];
            t++;
        }
        if(t>=1)v.push_back({prime[i],t});
    }
    printf("%d",v[0].first);
    if(v[0].second>=2)printf("^%d",v[0].second);
    for(int i=1;i<v.size();i++)
        (v[i].second>=2)?printf("*%d^%d",v[i].first,v[i].second):printf("*%d",v[i].first);
    printf("\n");
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值