pat乙级1001,1002

1001解题思路:
1.用while+if-else来控制循环次数(砍得的次数)和判断奇数偶数

我的代码如下:

#include  
using namespace std;

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

别人的代码:

#include 
using namespace std;
int main() {
 int n, count = 0;
 cin >> n;
 while (n != 1)
  {
	 if (n % 2 != 0)      //这个循环就是判断奇数的,n为奇数*3+1完了,在下一句除2 这样就省掉了加括号的麻烦 抓住了不管奇数还是偶数                         
//都有除2的特点 如果n为偶数不执行此语句,直接再下面除2
		 n = 3 * n + 1;   
	 n = n / 2;
	 count++;
 }
 cout << count;
 return 0; }

1002解题思路:
1.用string类来存储数据,不然的话double,long long类型的长度不够
2. 用for循环来计算各位数字之和
3. 用string类定义一个数组,其中成员是数字的拼音
4. 将数字和变量改为字符串类型,方便调用每个位数字,不用对数字除或求余
5. 通过循环从数字和的字符串中对应找到string类的数字拼音

my code:

#include
using namespace std;

int main()
{
	string s;
	cin >> s;
	int i,sum=0;
	for(i=0; i<s.length(); i++)     //s.length()计算字符串长度 
	{
		sum+=s[i]-'0';
	}
	string name[10]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};  //字符串用双引号括起来,字符用单引号括起来 
	
	string a = to_string(sum);
	
	for(i=0; i<a.length(); i++)
	{
		cout << name[a[i]-'0'];   //将数字转变为字符去存储方便调用每个位置上的数字,不用再除或求余啥的 
		if (i != a.length()-1)
			cout << ' ';
	}
	

	return 0;
}

other’s

#include 
#include 
using namespace std;
int main() 
{
	 string s;
	 cin >> s;
	 int sum = 0;
	 string str[10] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi","ba", "jiu"};   //
	 for (int i = 0; i < s.length(); i++)
	 	sum += (s[i] - '0');
	 	
	 string num = to_string(sum);
	 
	 for (int i = 0; i < num.length(); i++)
	 {
		 if (i != 0)        //题目要求最后一个拼音不能有空格,所以是先输出拼音,后输出空格,提前加一个if判断,当输入完最后一个拼音,循环都已经结束了
		 	cout << " ";
		 cout << str[num[i] - '0'];
	 }
	 
	 return 0; 
 }

1003解题思路:

pat乙级1001,1002_第1张图片
pat乙级1001,1002_第2张图片
pat乙级1001,1002_第3张图片
我的代码:

#include
#include
using namespace std;
/*
    解题思路:
    1.设置一个map,以输入的字符串的字母作为关键字值,然后统计每个字符的个数
    2.最终要确定p的位置和t的位置
    3.下面中最长的if的语句的理解:
        1.m['P']==1 && m['A']!=0 && m['T']==1 表示表示p,t的个数都为1,然后A的个数不为1
        2.m.size()==3 表示只含有p a t三个字符   //满足条件1
        3.t-p的值不为1,表示p与t之前必须有一个字符’A‘    //满足条件2
        4.p也表示'p'之前’A‘的个数,(t-p-1)表示’p‘与’t‘之间所有'a'的个数,s.length()-t-1表示’t‘之后所含的所有’a‘的个数  //满足条件3
        
*/
int main()
{
	int n,i,j,p,t;
	cin >> n;
	string s;
	for(i=0; i<n; i++)
	{
		cin >> s;
		map<char, int> m;
		for(j=0; j<s.length(); j++)
		{
			m[s[j]]++;       //统计每个字符的个数 
			if(s[j]=='P')
				p=j;          //如果字符是p,则记录p的位置;如果字符是T,则记录t的位置
			if(s[j]=='T')
				t=j;
		}
		if(m['P']==1 && m['A']!=0 && m['T']==1 && m.size()==3 && t-p!=1 && p*(t-p-1)==s.length()-t-1)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}

1004解题思路:
1.首先根本不用存储每次输入的学生的信息,重点是要知道成绩最值的学生的姓名和学号,所以用变量来存储这些信息。“铁打的营盘流水的兵”恰如其分描述铁打的营盘类似成绩最值的姓名和学号,而流水类似不断敲入的学生成绩,姓名和学号

1005解题思路:
1.设置一个数组arr[]其中表示对输入数字进行c式处理后对应下标为1
比如:输入5 ,第一次c式处理后为8,则将arr[8]的值为1
先判断arr值是否为1,是则退出循环,输入下一个值判断,不是另其值为1
2.注意arr数组的空间大小为10000否则只是部分正确
代码:

#include
#include
#include
using namespace std;
int arr[10000];
bool cmp(int a, int b)
{
    return a>b;
}

int main()
{
    int k,n,flag=0;
    cin >> k;
    vector<int> v(k);//定义一个数组
    //for中嵌套while,外面一共循环k次,里面就是对数字处理并且标记对应arr数组中的值为1
    //如果在while中判断数字有1则直接输入下一个数
    for(int i=0; i<k; i++)
    {
        cin >> n;
        v[i]=n;   //数组存放对应的数字
        while(n!=1)
        {
            if(n%2!=0)
                n=3*n+1;
            n/=2;
            /*?*/
            if(arr[n]==1)
                break;
            arr[n]=1;
        }
    }
    sort(v.begin(), v.end(), cmp); //将数组按照从大到小的顺序排列
    for(int i=0; i< v.size(); i++)
    {
        if(arr[v[i]]==0) //表示
        {
            if(flag==1)
                cout << " ";
            cout << v[i];
            flag=1;

        }
    }
    return 0;
}

1006
解题思路:就是取百位然后循环输出B,求出十位循环输出S,求出个位循环输出1–n
参考代码:

#include
using namespace std;
/*
    思路就是取百位然后循环输出B,求出十位循环输出S,求出个位循环输出1--n
*/
int main()
{
    int n;
    cin >> n;
    for(int i=1; i<=n/100; i++)
        cout << 'B';
    for(int j=1; j<=n%100/10; j++)
            cout << 'S';
    for(int k=1; k<=n%10; k++)
            cout << k;
    return 0;
}

1007
解题思路:ans表示有多少对数字
遍历从0–n相邻且相差2的数字,然后判断是否为素数

参考代码:

#include
using namespace std;
/*
  解题思路:ans表示有多少对数字
        遍历从0--n相邻且相差2的数字,然后判断是否为素数
*/
int f(int n)
{
    for(int i=2; i*i<=n; i++)
        if(n%i==0)
            return 0;
    return 1;
}
int main()
{
    int n,ans=0;
    cin >> n;
    for(int i=2; i<=n-2; i++)
    {
        if(f(i) && f(i+2))
            ans++;
    }
    cout << ans;
    return 0;
}

解题思路:
pat乙级1001,1002_第4张图片
pat乙级1001,1002_第5张图片

参考代码:

#include
#include  //reverse()使用此头件
#include  //vector使用此头文件
using namespace std;
int main()
{
    int n,m;
    cin >> n >> m;
    vector<int > a(n);
    for(int i=0; i<n; i++)
        cin >> a[i];
    m%=n;
    if(m!=0)
    {
        reverse(a.begin(),a.end());  //a.begin()是指针,指向数组第一个元素;a.end()也是指针,指向a[6]
        reverse(a.begin(),begin(a)+m);  //reverse中不会将第2部分的值也倒转,而是把他之前的值倒转
        reverse(begin(a)+m,a.end());  //从上一位置开始
    }
    for(int i=0; i<n-1; i++)
        cout << a[i] << " ";
    cout << a[n-1];
    return 0;
}

1009
解题思路:
利用栈先进后出的思想来倒叙输出字符串
首先,将字符串压入栈,访问栈顶元素,弹出当前栈顶元素。
由于题目要求,字符串之间有空格并且最后一个字符串没有空格,下面就循环先输出空格再输出字符串然后弹出
参考代码:


#include
#include
using namespace std;

int main()
{
    stack<string> v;
    string s;
    while(cin >> s)
        v.push(s);
    cout << v.top();
    v.pop();
    while(!v.empty())
    {
        cout << " " << v.top();
        v.pop();
    }
    return 0;
}

1010
解题思路:
1.每次输入两个变量,不用存放到数组中,规律是每次输出第一个变量*第二个变量;第二个变量-1
2.对于上面规律使用前提是第二个变量不为0,若为0,不执行语句,进入下一次循环,看,在这里并不是
3. 使用continue,而是循环中嵌套一个if,这样当条件不满足时,自动不执行if中的语句,直接进入下一次循环
4.对于先输出数值,后输出空格,但在最后不能有空格的套路是用flag标记(你懂的)
5.对于零项多项式和全部都是常数项而言,当整个循环结束后还是用flag==0判断,并输出0 0

注意事项:
1 . 0项多项式表示前面没有式子,这样在循环到最后一个式子时输出 0 0
2.对于前面有式子最后一个是0项多项式,这根本不叫0项多项式
3.对于目前这个程序而言根本无法测试出输出"0 0"这个式子因为循环一直不结束,之所以能输出想要的结果那是因为在循环内部就给出值了

参考代码:

#include
using namespace std;
int main()
{
    int flag=0;
    int a,b;
    while(cin >> a >> b)
    {
        if(b!=0)
        {
            if(flag==1)
                cout << " ";
            cout << a*b << " " << b-1;
            flag=1;
        }
    }
    if(flag==0)
        cout << "0 0";
}

1012
解题思路:
1.将输入的数字存放到对5求余对应下标的二维数组中
2.计算A1–A5
1.A2:就是下标为偶数的加 - 下标为奇数的和
3.输出,用printf简单
注意事项:
1.==不是=
2.对于某个点一直过不去,重新敲一遍

/*
    解题思路:
    1.将输入的数字存放到对5求余对应下标的二维数组中
    2.计算A1--A5
            1.A2:就是下标为偶数的加 - 下标为奇数的和
    3.输出,用printf简单
*/
#include
#include
using namespace std;
int main()
{
    int n,digit,A1=0,A2=0,A3=0,A5=-1;   //对应的变量注意设置出来
    double A4=0.0;
    cin >> n;
    vector<int> a[5];

    for(int i=0; i<n; i++)
    {
        cin >> digit;
        a[digit%5].push_back(digit);      //这里使用push_back就是将数字压入,自动生成一个二维数组
                                        //注意写法:数组[下标].push_back(要填入的数字);
    }

    for(int i=0; i<5; i++)
        for(int j=0; j<a[i].size(); j++)
        {
            if(i==0 && a[i][j]%2==0)
                A1+=a[i][j];
            if(i==1 && j%2==0)
                A2+=a[i][j];
            if(i==1 && j%2!=0)
                A2-=a[i][j];
            if(i==2)
                A3++;
            if(i==3)
                A4+=a[i][j];
            if(i==4 && a[i][j]>A5)     //一定要是大于A5
                A5=a[i][j];
        }
    for(int i=0; i<5; i++)
    {
        if(i!=0)
            cout << " ";
        if(i==0 && A1==0 || i!=0 && a[i].size()==0)
        {
            cout << "N";
            continue;
        }
        if(i==0)
            printf("%d",A1);
        if(i==1)
            printf("%d", A2);  //计算出结果为何不直接输出值?因为每一次输出都有条件限制,对于不存在的数输出N,
                            //为了保证思路的理解,就设置成循环,如果不满足条件就输出N,否则按照对应的值输出
        if(i==2)
            printf("%d",A3);
        if(i==3)
            printf("%.1f",A4/a[i].size());
        if(i==4)
            printf("%d",A5);
    }
    return 0;
}

1013
解题思路:
将从第M个素数到第N个素数放到数组中

参考代码:

#include
#include
using namespace std;

bool isprime(int a)
{
    for(int i=2; i*i<=a; i++)
        if(a%i == 0)
            return false;
    return true;
}

int main()
{
    int M,N,num=2,cnt=0;
    cin >> M >> N;
    vector<int> v;
    /*
        1.从素数列中找到第m个到第n个放到数组中
        2.用while循环,含义是循环至少执行N次,也就是M=5,N=27,循环至少执行27次,表示
          从第一素数到第27个素数,而且cnt必须从0开始,因为num初值为2,进入到isprime函数中,
          cnt++表示1与2为第一个素数相对应
        3.num++与循环的判断条件无关,循环的判断条件是第几个素数,其中cnt为N-1就表示第N个素数
          因为cnt从0开始
    */
    while(cnt < N)       //cnt的值从0开始,自然要小于N
    {
        if(isprime(num))
        {
            cnt++;
            if(cnt >= M)
                v.push_back(num);
        }
        num++;
    }
    cnt=0;
    /*
        对于每次先输出数字再输出空格,且最后一个不为空格,且每行10个的思想:
        1.将输出空格代码放前面,用if的一个条件判断(避开第一次输出空格),
          然后紧接着输出数字,依次循环
        2.对于每次换行,都希望能与1中的if语句相关联。这样保证每次换行时不会先输出一个空格,
          再输出数值,对于每次输出10个,那么每行的第一个就是1,11,21,31.....求余为1
          这样在if中可以设置%10!=1输出空格,当然在最后要有如果求余10就输出换行
    */
    for(int i=0; i<v.size(); i++)
    {
        cnt++;
        if(cnt%10 != 1)
            cout << " ";
        cout << v[i];
        if(cnt%10 == 0)
            cout << endl;
    }
}


/**********我的代码但是超时**********/
/*
    解题思路:
    1.素数公式判断
    2.从第m个素数到第n个素数
    主要是找到第一个
        1.用while,条件是k==n;k=0
*/
#include
using namespace std;
bool f(int n)
{

    for(int i=2; i*i<=n; i++)
        if(n%i==0)
           return false;
    return true;
}

int s(int n)  //找到第n个素数
{
    int k=1,i=3;
    if(n==1)
    {
        return 2;
    }
    while(k!=n)
    {
        if(f(i))
            k++;
        i+=2;
    }
    return i-=2;
}

int main()
{

    int m,n,now=0,flag=0;
    cin >> m >> n;
    for(int i=s(m); i<=s(n); i++)
    {
        if(f(i))
        {
            if(flag==1)
                cout << " ";
            cout << i;
            flag=1;
            now++;
    /*
        之前是换行后,先输出空格然后再输出值,我改为每次换行后,将flag的值修改,这样进入
        下次循环时,就不会输出空格,并且按照最后一个不为空格的方式输出
    */
            if(now%10==0)
            {
                cout << endl;
                flag=0;
            }
        }

    }


    return 0;
}

1014
解题思路:
1.用两次while分别找出a,b字符串中第一个和第二个相同字符
2.同样也用while遍历循环c,d两个字符串
参考代码:

#include
#include
using namespace std;
/*
    解题思路:
    1.用两次while分别找出a,b字符串中第一个和第二个相同字符
    2.同样也用while遍历循环c,d两个字符串
*/
int main()
{
    string a,b,c,d;
    char t[2];
    cin >> a >> b >> c >> d;
    int i=0,j=0,e=0;
    //找到第一个相同的字符
    while(i<a.length() && i<b.length())
    {
        if(a[i]==b[i] && ('A'<=a[i] && a[i]<='G'))
        {
            t[0]=a[i];
            break;
        }
        i++;
    }
    i++;

    //找到第二个相同的字符
    while(i<a.length() && i<b.length())
    {
        if(a[i]==b[i])
        {
            if(isdigit(a[i]) || ('A'<=a[i] && a[i]<='N'))  //isdigit(a[i])判断a[i]是否为数字字符
            {
                t[1]=a[i];
                break;
            }
        }
        i++;
    }

    //找到第三个字符
    while(j<c.length() && j<d.length())
    {
        if(c[j]==d[j] && isalpha(c[j]))          //isalpha(c[j])判断c[j]是否为字母
        {
            e=j;
            break;
        }
        j++;
    }


    char sa[7][5]={"MON ","TUE ","WED ","THU ","FRI ","SAT ","SUN "};
    cout << sa[t[0]-'A'];
    int m=isdigit(t[1])? t[1]-'0': t[1]- 'A' + 10;    //切记这里用一个整形变量m来接受条件判断的结果,最后在输出
    printf("%02d:%02d",m,j);       //采用c的方式输出,是为了当数字为1位时,前面有0补充;否则直接输出2位数

    return 0;
}


知识总结:

isdigit(A)   //判断A是否为数字字符
isalpha(A)   //判断A是否为字母

1015德才论
解题思路:
1.用一个结构stu来存放数据信息
2.设置一个排序函数,总分不同按照从大到小排列,总分相同,按照按照德分从大到小排列;德分相同,按照
学号从小到大输出
3.设置1个结构数组,一个临时变量结构用来存放每次的输入;循环中嵌套if判断,将对应的结构压入栈中,也就形成了二维数组
4.最后压栈进行排序后并输出
注意事项:
在输入时,用scanf格式控制字符来输入,不会超时
参考代码:

#include
#include
#include
using namespace std;
/*
    解题思路:

*/
struct node
{
    int num,de,cai;
};

int cmp(struct node a, struct node b)
{
    if((a.de+a.cai)!=(b.de+b.cai))
        return (a.de+a.cai) > (b.de+b.cai);   //如果总分数不同,就按照最大到小的顺序排列
    else if(a.de!=b.de)                    //如果总分数相同,但德分不同,按照德分从大到小排列
        return a.de>b.de;         //从大到小
    else
        return a.num<b.num;            //从小到大
}


int main()
{
    int low,high,n;
    cin >> n >> low >> high;
    node temp;
    vector<node> v[4];
    int total=n;
    for(int i=0; i<n; i++)
    {
        scanf("%d %d %d", &temp.num,&temp.de, &temp.cai);
        if(temp.de < low || temp.cai < low)
            total--;
        else if(temp.de >= high && temp.cai >= high)
            v[0].push_back(temp);
        else if(temp.de >= high && temp.cai < high)
            v[1].push_back(temp);
        else if(temp.de < high && temp.cai < high && temp.de >= temp.cai)
            v[2].push_back(temp);
        else
            v[3].push_back(temp);

    }
    cout << total << endl;
    for(int i=0; i<4; i++)
    {
        sort(v[i].begin(),v[i].end(),cmp);
        for(int j=0; j<v[i].size(); j++)
            cout << v[i][j].num << " " << v[i][j].de << " " << v[i][j].cai <<endl;
    }
    return 0;

}

知识总结:

自定义排序:
struct stu
{
	int mark,num;
};
bool cmp(stu a, stu b)
{
	if(a.mark != b.mark)
		return a.mark > b.mark  //降序排列
	else
		return a.num<b.num      //mark相同按照num的升序排列
}
vector<stu> v[4];   //结构数组
sort(v[i].begin(),v[i].end(),cmp);  //对数组进行相应的排序

1016
解题思路:
1.用string存放要输入的字符串数组,用int来存放其他类型
2.判断是否有相同的字符,并且记录个数,最后通过循环来累加起来
3.两次循环记录相同数字的个数
4.根据相同数字个数是否为0,否就再循环算出对应的值
参考代码

#include
#include
using namespace std;
/*
    解题思路:
    1.用string存放要输入的字符串数组,用int来存放其他类型
    2.判断是否有相同的字符,并且记录个数,最后通过循环来累加起来
*/
int main()
{
    string a,b;
    int a1,b1,num1=0,num2=0,suma=0,sumb=0;    //a1,b1表示要找的数字,num1,num2表示个数,suma,sumb表示和
    cin >> a >> a1 >> b >> b1;
    for(int i=0; i<a.size(); i++)      //记录相同数字的个数
    {
        if(a1 == a[i]-'0')
            num1++;
    }
    for(int i=0; i<b.size(); i++)        //记录相同数字的个数
    {
        if(b1 == b[i]-'0')
            num2++;
    }

    if(num1!=0)  
        suma=a1;   
    if(num2!=0)
        sumb=b1;
    for(int i=1; i<num1; i++)
        suma=suma*10+a1;
    for(int i=1; i<num2; i++)
        sumb=sumb*10+b1;
    cout << suma+sumb;
    return 0;
}

1017
解题思路:
1.模拟手动求余的过程
2.对于1000位的数字,用string;对于输出商,不用变量存储,直接输出
参考代码:

int main()
{
    string s;
    int a,t=0,temp=0;
    cin >> s >> a;
    t=(s[0]-'0')/a;    //t就是商
    /*
        1.对于只有一位的数,直接输出商t
        2.对于2位及2位以上,如17 ,93 这种情况,前者就不输出,后者输出1
    */
    if((t != 0 && s.length() > 1) || s.length() == 1)
        cout << t;
    temp = (s[0]-'0')%a;    //保存余数
    /*
        i从1开始,先计算下一位数的数,输出商,保存余数
    */
    for(int i=1; i<s.length(); i++)   
    {
        t=(temp*10+s[i]-'0')/a;       
        cout << t;
        temp=(temp*10+s[i]-'0')%a;
    }
    cout << " " << temp;
    return 0;
}

1018
解题思路:
1.统计甲赢的次数,乙赢的次数。甲输的次数就是赢的次数,同理,乙也是如此。平的次数就是总数-甲赢的次数-乙赢的次数
2.如何确定赢次数最多的手势?
答:将BCJ默认为012,在统计赢的次数时,记录甲乙赢的时候,对应手势所对应的下标的数组++,最后选出最大的个数,并且记住
下标,最后定义一个字符数组"BCJ"这样刚才统计的下标就可以字符数组相对应
参考代码:

#include
using namespace std;
/*
    解题思路:
    1.jiawin  yiwin 分别记录甲赢的次数和已赢的次数
    2.a[]  b[]两个数组分别统计B,J,C赢的次数,默认为012
    3.最后对数组元素比较得出最大的数组下标,同时设计一个变量,也是BJC这样就输出了对应的值
*/
int main()
{
    int jiawin=0,yiwin=0;
    int jia[3]={0};
    int yi[3]={0};
    char s,t;
    int n;
    cin >> n;
    for(int i=0; i<n; i++)
    {
        cin >> s >> t;
        if(s=='B' && t=='C')
        {
            jiawin++;
            jia[0]++;
        }
        else if(s=='C' && t=='J')
        {
            jiawin++;
            jia[1]++;
        }
        else if(s=='J' && t=='B')
        {
            jiawin++;
            jia[2]++;
        }
        else if(s=='C' && t=='B')
        {
            yiwin++;
            yi[0]++;
        }
        else if(s=='J' && t=='C')
        {
            yiwin++;
            yi[1]++;
        }
        else if(s=='B' && t=='J')
        {
            yiwin++;
            yi[2]++;
        }
    }
    cout << jiawin << " " << n-jiawin-yiwin << " " << yiwin << endl << yiwin << " " << n-jiawin-yiwin << " " << jiawin << endl;
    int maxjia=jia[0]>=jia[1]?0:1;    //设计大于等于的目的是:首先字母已经从字母序从小到大排列,当a[0]==a[1]时,结果max1还是0,不然最后max1就指向j
    maxjia=jia[maxjia]>=jia[2]?maxjia:2;

    int maxyi=yi[0]>=yi[1]?0:1;
    maxyi=yi[maxyi]>=yi[2]?maxyi:2;
    char k[4]={"BCJ"};
    cout << k[maxjia] << " " << k[maxyi];
    return 0;
}

注意:BCJ对应012

1019
解题思路:
1.还是用string类来存放输入的数字
2.自定义函数降序排列+结合sort升序排列+字符串转化为数字函数stoi()+数字转化为字符串函数to_string()+对不足四位的数补充0的相关函数s.insert(i,j,k)(题目要求四位输出)+do-while(当先输入0000时,还可以输出)
参考代码:

#include
#include
using namespace std;
bool cmp(char a, char b)
{
    return a>b;
}
int main()
{
    string s;
    cin >> s;
    s.insert(0,4-s.length(),'0');    //输入的数字不满足4位,则前补充0
    do          //先输入do-while是为了,当输入6174时还能执行一次循环
    {
        string a=s,b=s;
        sort(a.begin(),a.end(),cmp);  //数字以从大到小排列
        sort(b.begin(),b.end());      //默认为从小到大
        int result=stoi(a)-stoi(b);    //stoi将字符串转化为整数
        s=to_string(result);            //将数字转化为字符
        s.insert(0,4-s.length(),'0');
        cout << a << " - " << b << " = " << s << endl;
    }while(s!="6174" && s!="0000");
    return 0;
}


/*
    知识总结:
    1.对字符串第i个位置开始,插入j个k
        s.insert(i,k,j);
    2.对字符串进行排序
        sort(s.begin(),s.end(),cmp);   //按照cmp的顺序排列
        sort(s.begin(),s.end());         //默认为从小到大排列
    3.stoi(str)   //将字符串转化为整数
    4.to_string(a)          //将数字转化为字符串
*/

知识总结:

```cpp
    1.对字符串第i个位置开始,插入j个k
        s.insert(i,k,j);
    2.对字符串进行排序
        sort(s.begin(),s.end(),cmp);   //按照cmp的顺序排列
        sort(s.begin(),s.end());         //默认为从小到大排列
    3.stoi(str)   //将字符串转化为整数
    4.to_string(a)          //将数字转化为字符串
    ```

1020
解题思路:
1.构建一个结点里面有3个结构成员,分别是mount种类库存,price种类总价,unit种类单价
2.自定义cmp,按照单价的降序排列
3.设置循环,先紧着单价最高的使,然后用单价次一级的…这样最后利润一定是最高的
参考代码:

#include
#include
#include
using namespace std;
/*
    解题思路:
    1.构建一个结点里面有3个结构成员,分别是mount种类库存,price种类总价,unit种类单价
    2.自定义cmp,按照单价的降序排列
    3.设置循环,先紧着单价最高的使,然后用单价次一级的....这样最后利润一定是最高的
*/

struct mooncake
{
    float mount,price,unit;
};
int cmp(mooncake a, mooncake b)
{
    return a.unit > b.unit;
}
int main()
{
    int n,need;
    cin >> n >> need;
    vector<mooncake> a(n); //且记要定义数组长度大小,否则不能连续for输入
    for(int i=0; i<n; i++)
        scanf("%f",&a[i].mount);  //切记,float类型的scanf是%f
    for(int i=0; i<n; i++)
        scanf("%f",&a[i].price);
    for(int i=0; i<n; i++)
        a[i].unit=a[i].price/a[i].mount;

    sort(a.begin(),a.end(),cmp);

    float result=0.0;
    for(int i=0; i<n; i++)
    {
        if(a[i].mount <= need)
            result = result+a[i].price;
        else
        {
            result=result+a[i].unit*need;
            break;
        }
        need=need-a[i].mount;
    }
    printf("%.2f",result);
    return 0;
}

知识总结:
对于vector定义的数组连续for输入需要指明数组长度

#include
#include
using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<int> a(n),b(n);  //不定以数组长度大小,否则不能连续for输入
    for(int i=0; i<n; i++)
        cin >> a[i];
    for(int i=0; i<n; i++)
        cin >> b[i];
    return 0;
}

1021
解题思路:
用string存储整数,for遍历循环,定义9个长度的数组,对应的值++,最后按顺序输出数组元素不为0的

#include
using namespace std;
/*
    解题思路:
    1.
*/
int main()
{
    string s;
    int a[10]={0};
    cin >> s;
    for(int i=0; i<s.length(); i++)
        a[s[i]-'0']++;
    for(int i=0; i<10; i++)
    {
        if(a[i]!=0)
            cout << i << ':' << a[i] << endl;
    }
    return 0;
}

注意事项:
有时候,用vector发生错误,就直接用普通数组定义法

1022
解题思路:
1.将余数存入数组,while的判断条件sum!=0
2.将数组倒叙输出,j=i-1,
3.不要忘记sum的0,输出0,return 0
4.不要用VEctor压栈
参考代码:

#include
using namespace std;
/*
    解题思路:
    1.将余数存入数组,while的判断条件sum!=0
    2.将数组倒叙输出,j=i-1,
    3.不要忘记sum的0,输出0,return 0
    4.不要用VEctor压栈
*/

int main()
{
    int sum,A,B,D,i=0;
    cin >> A >> B >> D;
    int a[100];
    sum=A+B;
    if(sum==0)
    {
        cout << 0;
        return 0;
    }
    while(sum!=0)
    {
        a[i++]=sum%D;
        sum/=D;
    }
    for(int j=i-1; j>=0; j--)
        cout << a[j];
    return 0;
}


1023
解题思路:
1.没理解题意,切记数组是存放数字的个数
2.先找出第一个不为0的数,并输出
3.将所有0输出
4.再输出所有第一个不为0的数
5.双层for循环输出剩下的所有数,第一层for表示要输出的数字,第二层for表示要输出的个数
参考代码:

#include
using namespace std;
int main()
{
    int a[10];
    int t;
    for(int i=0; i<10; i++)
        cin >> a[i];
    for(int i=1; i<10; i++)
    {
        if(a[i]!=0)
        {
            cout << i;
            t=i;           //t存放第一个不为0的数
            break;
        }
    }

    for(int i=0; i<a[0]; i++)   //输出所有的0
        cout << 0;
    for(int i=0; i<a[t]-1; i++)   //输出所有第一个不为0的数,因为之前输出了一个,所以这里就少输出1个
        cout << t;
    for(int i=t+1; i<10; i++)
        for(int j=0; j<a[i]; j++)
            cout << i;
    return 0;

}

知识总结:

#include
#include
#include
#include
using namespace std;
/*
    解题思路:
    1.将余数压栈,sum>D
*/

int main()
{
    vector<int> a(5);      //用vector定义数组长度就是后面加(n)n表示数组长度
    for(int i=0; i<a.size(); i++)    //遍历数组时,i
        cout << a[i];
    int k=333;
    string s=to_string(k);      //将数字转化为字符串时用to_string切记是小写的to_string
    cout << s;
    return 0;
}

1024
解题思路:
1.从E将字符串一分为2,但第一个字符串不包括符号位
2.将后面的字符串转化为整数放到n
3.根据n 的正负,选择输出不同的情况
4.切记,当n为正数时,还要知道.和E之间的数字个数与n之间的关系,它们也是不同的输出
参考代码:

#include
using namespace std;
int main()
{
    /*
        解题思路:
        1.从E将字符串一分为2,但第一个字符串不包括符号位
        2.将后面的字符串转化为整数放到n
        3.根据n 的正负,选择输出不同的情况
        4.切记,当n为正数时,还要知道.和E之间的数字个数与n之间的关系,它们也是不同的输出
    */
    string s;
    cin >> s;
    int i=0;

    while(s[i]!='E')     //此时i表示E所在的位
        i++;

    string t=s.substr(1,i-1);     //t保存E之前的字符串,不包括符号位

    int n=stoi(s.substr(i+1));     //将E之后下一位开始到字符串结束的转化为数字

    if(s[0]=='-')
        cout << "-";

    cout << n << endl;
    if(n<0)
    {
        cout << "0.";

        for(int j=0; j<abs(n)-1; j++)  //输出0
            cout << '0';

        for(int j=0; j<t.length(); j++)   //遇到.就不输出
            if(t[j] != '.')
                cout << t[j];
    }
    else
    {
        cout << t[0];
        int cnt,j;

        for(j=2, cnt=0; j<t.length() && cnt<n; j++,cnt++)  //若.和E之间的数字个数大于n,则只输出n个数字来
            cout << t[j];

        /*
            根据上面for结束的情况,一种是j==t.length()表示.和E之间的数字个数小于n,后面直接输出(n-cnt)个0;
            另一种是cnt==n,表示.和E之间的数字个数大于或等于n,就得先输出. 然后从i=j开始一直到字符完输出
        */
        if(j==t.length())
        {
            for(int k=0; k<n-cnt; k++)
                cout << '0';
        }
        else
        {
            cout << '.';
            for(int k=j; k<t.length(); k++)
                cout << t[k];
        }
    }
    return 0;
}

/*


知识总结:

知识总结:
1.s.substr() 截取字符串中的子串
    s.substr(4)  //表示从4开始到下标结束
    s.substr(5,3)   //表示从5开始3个字符*/

我的代码:

#include
#include
using namespace std;
/*
    解题思路:
    1.用string存放输入,判断E之后是+还是-
    2.若为-,
        先输出0. + (后面的值-符号和.之间有几位)*输出0  + 输出s[1]  + 输出s[3]-->s[E所在的前一位]
      若为+,
        先输出s[1] + (输出第3位开始到E之前的所有数字) + (后面的值-小数点和E之间的数字个数)*输出0
    3.若第一个字符为-,必须先输出-

*/

int main()
{
    string s,s1;
    cin >> s;
    int t,m,k;
    int sum=0;
    for(int i=0; i<s.length(); i++)
    {
        if(s[i]=='E')
        {
            t=i;
            break;
        }
    }
    //计算E之后符号后的数值
    for(int i=t+2; i<s.length(); i++)
    {
        sum+=s[i]-'0';
        sum*=10;
    }
    sum/=10;
    if(s[0]=='-')
        cout << '-';
    if(s[t+1]=='-')
    {
        cout << 0 << '.';
        for(int i=1; i<=sum-1; i++)
            cout << 0;
        cout << s[1];
        for(int i=3; i<t; i++)
            cout << s[i];
    }
    else
    {
        cout << s[1];
        for(int i=3; i<t; i++)
            cout << s[i];
        for(int i=1; i<=sum-(t-3); i++)
            cout << 0;
    }
    return 0;
}


1027
解题思路:
1.i表示从中间一行向外扩展的层数,比如样例中i为2
2.3+5+7+…+2i+1=i(i+2)这是上半部分字符的个数,一共有2i*(i+2)+1个字符。当2i(i+2)+1>N时,令row=i-1表示向外扩大的
最大层数
3.通过3个for嵌套循环输出字符:第一for控制打印的层数;第二个for控制打印空格(row-i);第三for控制打印字符(2i+1)(注意在每一行的最后面
不需要打印空格,直接换行就能形成样例的效果)
4.打印最中间一行
5.打印最后下半部分
6.输出剩余个数N-(2
i*(i+2)+1)

参考代码:

#include
using namespace std;

int main()
{
    int N,row=0;   //对row初始化否则超时
    char c;
    cin >> N >> c;
    for(int i=1; i<N; i++)
    {
        if((2*i*(i+2)+1)>N)
        {
            row=i-1;
            break;
        }
    }
    for(int i=row; i>=1; i--)
    {
        for(int k=row-i; k>=1; k--)
            cout << ' ';
        for(int j=2*i+1; j>=1; j--)
            cout << c;
        cout << endl;
    }
    for(int i=0; i<row; i++)
        cout << ' ';
    cout << c << endl;
    for(int i=1; i<=row; i++)
    {
        for(int k=row-i; k>=1; k--)
            cout << ' ';
        for(int j=2*i+1; j>=1; j--)
            cout << c;
        cout << endl;
    }
    cout << N-(2*row*(row+2)+1);
    return 0;
}

注意事项:
1.对row要赋初值,否则运行超时

1028
解题思路:
1.用字符串来存储,还是用铁打的营盘流水兵的思想
2.maxbirth=“1814/09/06”,minbirth=“2014/09/06"都是string类的,string的比较从左至右;对于输入判断"1814/09/06”<=tempbirth<=“2014/09/06”
参考代码:

#include
using namespace std;
/*
    解题思路:
   
*/
int main()
{
    int n,cnt=0;
    cin >> n;
    string name,birth,maxbirth="1814/09/06",minbirth="2014/09/06",maxname,minname;
    for(int i=0; i<n; i++)
    {
        cin >> name >> birth;
        if("1814/09/06"<=birth && birth<="2014/09/06")
        {
            cnt++;
            if(birth>maxbirth)
            {
                maxbirth=birth;
                minname=name;
            }
            if(birth<minbirth)
            {
                minbirth=birth;
                maxname=name;
            }
        }
    }
    cout << cnt;
    if(cnt!=0)
        cout << " " << maxname << " " << minname;
}

知识总结:
对于string字符串的比较是从左至右,按照ascii码比较

1029
解题思路:
1.以第一个字符串为准使用for循环,然后用a.find(b)来判断a中是否含有b,如果没有find返回string::npos;
并且用ans来表示第一个字符串和第二个字符串中不相同的且不相同的字符转化为大写也是不同的
2.最后输出ans
参考代码:

#include
#include
using namespace std;
/*
    解题思路:
    1.以第一个字符串为准使用for循环,然后用a.find(b)来判断a中是否含有b,如果没有find返回string::npos;
    并且用ans来表示第一个字符串和第二个字符串中不相同的且不相同的字符转化为大写也是不同的
    2.最后输出ans
    3.ans表示s1与s2中不相同的字符的字符串
*/
int main()
{
    string s1,s2,ans;
    cin >> s1 >> s2;
    for(int i=0; i<s1.length(); i++)
    {
        if(s2.find(s1[i]) == string::npos && ans.find(toupper(s1[i])) == string::npos)
            ans+=toupper(s1[i]);
    }
    cout << ans;
    return 0;
}

知识总结:
1.toupper()将小写字母转化成大写字母

#include
#include
using namespace std;
int main()
{
    /*
        1.toupper函数返回值为整数,在前面加个强制转化即可
    */
    char a='d';
    cout << (char)toupper(a);
}

2.a.find(b)查找a字符串中是否含有b

/*
        1.a.find(b)如果字符串a中包含字符串b则值不等于string::npos,否则相同。a,b可以是字符串也可以是字符
        2.npos是一个常数,用来表示不存在的位置
        3.a字符串中如果包含b,则返回0;否则返回4294967295也就是npos
*/
#include
#include
using namespace std;
int main()
{
    string a,b;
    cin >> a >> b;
    cout << a.find(b) << endl;
    cout << string::npos;
    return 0;
}

1030
解题思路:
1.先对数组进行排序,从小到大
2.通过两个for+if-else来找到满足题意的个数,外层for控制遍历整个数列,每次把v[i]当成最小的数,里面的for
就是判断当前v[i]是最小值时,所对应的满足题意的最多的个数。这里j=i+result与if(v[j]<=v[i]*p)用来表示:比如
上次循环后result=3,此时一开始就判断从当前i开始往后第3个数是否满足条件,满足就修改result的值,不满足result
值不变
参考代码:

#include
#include
#include
using namespace std;
int main()
{
    int n,temp,result=0;
    long long p;
    cin >> n >> p;
    vector<int>a(n);     //用vector定义有长度的数组时,数组名后用圆括号()中写数组长度
    for(int i=0; i<n; i++)
        cin >> a[i];
    sort(a.begin(),a.end());
    for(int i=0; i<n; i++)
    {
        for(int j=i+result; j<n; j++)
        {
            if(a[j]<=a[i]*p)
            {
                temp=j-i+1;
                if(temp>result)
                    result=temp;
            }
            else
                break;
        }
    }
    cout << result;
    return 0;
}

知识总结:
1.int:32位 0–2^32-1 long long: 64位 0–2^64-1
2.用vector定义有长度的数组时,数组名后用圆括号()中写数组长度

1031
解题思路:
1.定义一个函数isTrue判断字符串是否满足题意
2.对于全部满足输出"All passed"和不满足时输出字符串,可以使用flag
3.对于isTrue函数中通过for循环如果有不是数字的字符返回false,并且求出加权和sum
4.对于末尾数组中有x对应数组中10,设置一个临时变量tem,如果s[17]==‘x’,将tem=10,然后在判断是否与检验数组中的值对应

参考代码:

#include
using namespace std;
/*
    解题思路:
    1.定义一个函数isTrue判断字符串是否满足题意
    2.对于全部满足输出"All passed"和不满足时输出字符串,可以使用flag
    3.对于isTrue函数中通过for循环如果有不是数字的字符返回false,并且求出加权和sum
    4.对于末尾数组中有x对应数组中10,设置一个临时变量tem,如果s[17]=='x',将tem=10,然后在判断是否与
    检验数组中的值对应
*/


bool isTrue(string s)
{
    int a[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
    int b[11]={1,0,10,9,8,7,6,5,4,3,2};
    int sum=0;
    for(int i=0; i<17; i++)
    {
        if(s[i]<'0' || s[i]>'9')
           return false;
        sum+=(s[i]-'0')*a[i];
    }
    int temp=(s[17]=='X')?10:(s[17]-'0');
    return b[sum%11]==temp;           //如果最后一位检验相同,就返回True;否则返回false;也可以用if-else来写

}
int main()
{
    int n,flag=0;
    string s;
    cin >> n;
    for(int i=0; i<n; i++)
    {
        cin >> s;
        if(!isTrue(s))
        {
            flag=1;
            cout << s << endl;
        }
    }
    if(flag==0)
        cout << "All passed";
    return 0;
}

1032
解题思路:
1.将成绩放到学校编号对应的下标数组中,数组表示成绩之和
2.将max表示最大成绩的下标,由于题中,学校编号是从1开始,所以max初值为1,最后直接输出max1,和a[max1]。
参考代码:

#include
using namespace std;
/*
    解题思路:
    1.学校编号school,成绩和数组a[]={0},
    2.
*/
int main()
{
    int n,tem,max1=1,school;
    cin >> n;
    int a[n+1]={0};
    for(int i=0; i<n; i++)
    {
        cin >> school >> tem;
        a[school]+=tem;
    }
    for(int i=2; i<=n; i++)
    {
        if(a[i]>a[max1])
            max1=i;
    }
    cout << max1 << " " << a[max1];
    return 0;
}

注意事项:
1.定义数组a的长度时是n+1并且初值为0,因为题中含义是n个学生,所以学校的编号最大是n,查找最大值时的那个循环要能遍历到n,如果定义数组a的长度为n,那么最后成绩之和最大的是a[n](未赋初值的数组元素值是任意数),而最大值下标是n。
2.假设max1=1,也就是假设第一个学校的总分最大

解题思路:
解题思路:
1.三个函数:gcd求出最大公约数;func对分数进行化简,main输入a b c d
2.gcd用辗转相除求最大约数,
if(t20)
return t1;
else
gcd(t2,t1%t2);
3.gcd函数
1.如果m*n
0,分为2种情况:分母为0或分母为0,输出时加上判断分子是否为0
2.用flag表示异号为1,同号为0
3.对m,n都取绝对值,并向除
4.func函数:
1.解决Inf与分子为0的问题
2.定义flag,对m,n取整,x分子与分母的商
3.解决对于分数可能添加(-的问题
4.不论分子与分母是整除还是不整除,都先要输出x
5.如果对于整除的情况,根据flag看输不输出),并最后退出此函数
6.如果对于不是整除的情况,就要加上一个空格,以便让假分数的整数部分与分数分开
7.输出真分数的问题
1.先计算假分数去除整数部分的分子
2.然后调用gcd函数算出此时分母与分子的最大公约数
3.然后算出最简形式
4.按照分数的格式输出,注意最后还要根据flag看输出输出)。
5.main:
1.输入四个值a b c d
2.对于加法:通分手动算出分子分母然后将其作为参数代入func函数中求最简形式
3.对于减法,类似只是相减
4.对于乘法,类似根据手动的策略
5.对于除法,类似手动求倒数然后代入

参考代码:

#include 
#include 
#include
using namespace std;
long long a, b, c, d;       //为啥要是long long类型?答:必须范围足够大
/*

*/


//辗转相除求最大约数
long long gcd(long long t1, long long t2) {
   if(t2==0)
    return t1;
  else
    gcd(t2,t1%t2);
}

//对分数进行化简
void func(long long m, long long n)
{
 if (m * n == 0)
 {
     printf("%s", n==0?"Inf":"0");
     return ;
 }

 //异号是1,同号0
 bool flag=((m<0 && n>0) || (m>0 && n<0));
 m=abs(m); n= abs(n);
 long long x = m/n;

 printf("%s", flag?"(-":"");

 if (x!=0)
    printf("%lld",x);    //注意这里的格式化输出格式是小写的LLL 不是 11111111

 if (m%n==0)
 {
        printf("%s",flag?")":"");
    return ;
 }

 if (x!=0)
    printf(" ");
 m=m-x*n;
 long long t = gcd(m,n);
 m=m/t; n=n/t;
 printf("%lld/%lld%s",m,n,flag?")":"");
}

int main()
{
 scanf("%lld/%lld %lld/%lld", &a, &b, &c, &d);
 func(a,b); printf(" + "); func(c,d); printf(" = "); func(a*d+b*c,b*d);printf("\n");
 func(a,b); printf(" - "); func(c,d); printf(" = "); func(a*d-b*c,b*d); printf("\n");
 func(a,b); printf(" * "); func(c,d); printf(" = "); func(a*c, b*d);printf("\n");
 func(a,b); printf(" / "); func(c,d); printf(" = "); func(a*d, b*c);
 return 0;
}

易错点:

    if(m*n==0)
    {
        printf("%s",n==0?"Inf":"0");   
        return ;            // 易错:如果分子为0,或者分母为0,输出完Inf和0之后就应该退出程序;否则扣分
    }


    bool flag=((m<0 && n>0)||(m>0 && n<0));   //易错:flag设置为bool类型

解题思路:
插入排序:
i是数列b中第一个前一个数大于后一个数的位置
j相当于从i开始一直到b数列结束a数列与b数列完全匹配
对于插值排序:前面肯定是排好序的,也就是满足升序的序列,如果碰到前一位大于后一位则说明从此位的
后一位开始一直到数组结束都是乱序的,所以刚好用j从此位的后一位开始一直到数组结束,判断j是否为n,
如果是则为插序排列,然后对数组a进行sort排序(从头开始到i的下一位在排一次),表示他的下一次的插入排序,

归并排序:
1.k初值为1,每次给自己乘2,
2.由于b是排序过程中的某一此序列,所以用a数列循环和b数列进行比较,flag是一个标记,初值为1,若在循环中
a[j]!=b[j]则令flag为1(意思是还要进行循环)本来模拟一次就行,但是测试点要求模拟整个过程。
3.理解while的思路:
    1.首先要明确,测试点要求整个的算法是模拟归并排序的整个过程,但输出时是要通过此算法得出下一次归并
    排序的结果。
    2.首先设置flag为1进入循环,将flag默认为0,下来的for用于判断初始数列和b数列是否相同,若相同则为0,
    否则为1
    3.k自乘2,然后for循环+sort(a+i*k,a+(i+1)*2)排序,最后还要有sort(a+n/k*k,a+n);

参考代码:

#include
#include
#include
using namespace std;
int main()
{
    int n,i,j;
    cin >> n;
    int a[n],b[n];
    for(int i=0; i<n; i++)
        cin >> a[i];
    for(int j=0; j<n; j++)
        cin >> b[j];

    for(i=0; i<n-1 && b[i]<=b[i+1]; i++)
        ;
    for(j=i+1; j<n && a[j]==b[j]; j++)
        ;
    if(j==n)
    {
        cout << "Insertion Sort" << endl;
        sort(a,a+i+2);
    }
    else
    {
        cout << "Merge Sort" << endl;
        int k=1,flag=1;
        while(flag)
        {
            flag=0;
            for(int i=0; i<n; i++)
                if(a[i]!=b[i])
                    flag=1;
            k=k*2;
            for(int i=0; i<n/k; i++)
                sort(a+i*k,a+(i+1)*k);
            sort(a+n/k*k,a+n);
        }
    }

    for(int i=0; i<n; i++)
    {
        if(i!=0)
            cout << " ";
        cout << a[i];
    }
    return 0;
}

1036
解题思路;无
参考代码:

#include
using namespace std;
/*

*/
int main()
{
    int n;
    char c;
    cin >> n >> c;
    for(int i=0; i<n; i++)
        cout << c;
    cout << endl;
    for(int j=0; j<(n/2+n%2-2); j++)
    {
        cout << c;
        for(int k=0; k<(n-2); k++)
            cout << " ";
        cout << c << endl;
    }
    for(int i=0; i<n; i++)
        cout << c;
    return 0;
}

易错点:

对于50%的四舍五入是:n/2+n%2。比如17而言,结果为9
但是如果只有n/2,结果为8;并非四舍五入的结果

1037
解题思路1:
1.scanf输入
2.将数字通过题中所给的进制转化,然后化为一个整数,然后计算。
解题思路2:
1.通过诸位比较,得出:实际付的钱小于应该付的钱时,要交换顺序,保证后面减的时候,是大的减小的;并且输出
负号
2.用实际付得钱mnt-应该付的钱abc,模拟手动减

参考代码1:

#include
#include
#include
using namespace std;
/*
    解题思路:
    1.scanf输入
    2.将数字通过题中所给的进制转化,然后化为一个整数,然后计算。
*/
int main()
{
    int a,b,c,a1,b1,c1;
    scanf("%d.%d.%d",&a,&b,&c);
    scanf("%d.%d.%d",&a1,&b1,&c1);
    int P,A;
    P=c+b*29+a*17*29;
    A=c1+b1*29+a1*17*29;
    int k=A-P;
    if(k<0)
    {
        cout << '-';
        k=abs(k);
    }
    cout << k/(17*29) << '.' << (k%(17*29))/29 << '.' << (k%(17*29))%29;
    return 0;
}

参考代码2;

#include
#include
using namespace std;
int main()
{
    int a,b,c,m,n,t,x,y,z;
    scanf("%d.%d.%d %d.%d.%d",&a,&b,&c,&m,&n,&t);
    if(a>m || (a==m && b>n) || (a==m && b==n && c>t))
    {
        swap(a,m);
        swap(b,n);
        swap(c,t);
        cout << "-";
    }
    z=c>t?29+t-c:t-c;
    n=c>t?n-1:n;
    y=b>n?17+n-b:n-b;
    x=b>n?m-1-a:m-a;
    printf("%d.%d.%d",x,y,z);
    return 0;
}

注意事项:
1.abc表示应该付款值,mnt表示实际付款值,如果实际付款值小于应该付款值,则交换位置,并输出符号,因为最后都是用大的减去小的也就是用mnt-abc模拟手动减法

1038
解题思路1:
1.先输入一堆数字放到数组中,然后再输入k,随后把要查找的数放到数组中
2.然后在循环查找原来数据中要查找数字的个数,并放入数组中,最后循环输出

参考代码1:

#include
using namespace std;
/*
    解题思路:
    1.先输入一堆数字放到数组中,然后再输入k,随后把要查找的数放到数组中
    2.然后在循环查找原来数据中要查找数字的个数,并放入数组中,最后循环输出
*/
int main()
{
    int n;
    cin >> n;
    int a[n];
    
    for(int i=0; i<n; i++)
        cin >> a[i];
        
    int k;
    cin >> k;
    int b[k],c[k]={0};
    
    for(int j=0; j<k; j++)
        cin >> b[j];
    
    for(int s=0; s<k; s++)
        for(int l=0; l<n; l++)
        {
            if(a[l]==b[s])
                c[s]++;
        }
        
    for(int i=0; i<k; i++)
    {
        if(i!=0)
            cout << " ";
        cout << c[i];
    }
    return 0;
}

解题思路2:
1.将成绩作为下标,然后对应的元素值++
2.最后直接根据输入的值,循环输出

#include
#include
#include
using namespace std;
int main()
{
    int n,temp;
    cin >> n;
    vector<int>b(101);
    for(int i=0; i<n; i++)
    {
        cin >> temp;
        b[temp]++;
    }
    int m;
    cin >> m;
    for(int i=0; i<m; i++)
    {
        scanf("%d", &temp);//这里要用scanf否则超时
        if(i!=0)
            printf(" ");
         printf("%d", b[temp]);
    }
    return 0;
}

注意事项:
对于for循环中有输入+输出,其实在输入时,只有敲回车,才会输出要输出的值,如果用空格将输入分开,则结果直接根据根据循环次数输出对应的值:

#include 
#include 
#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    vector<int>b(101);
    int m=4;
    int temp;
     for (int i = 0; i < m; i++)
    {
         scanf("%d", &temp);
         if (i != 0)
            printf(" ");
         printf("0");
     }
     return 0;
 }

pat乙级1001,1002_第6张图片
pat乙级1001,1002_第7张图片

1039
解题思路1:
1.用字符串s1,s2分别存储摊主的串珠和小红想做的串珠
2.以s2为基准,for循环,再嵌套for循环s1,如果字符相同则将s1,s2字符都改成#
3.算出s1中不为#的字符个数,算出s2中为#的字符个数,
4.if判断如果s2中#的个数等于s2的字符长度,则输出yes和s1中不为#的字符个数;如果
s2中#的个数不等于s2的字符长度,则输出剩余的字符个数

参考代码:

#include
using namespace std;
/*
    解题思路:
    1.用字符串s1,s2分别存储摊主的串珠和小红想做的串珠
    2.以s2为基准,for循环,再嵌套for循环s1,如果字符相同则将s1,s2字符都改成#
    3.算出s1中不为#的字符个数,算出s2中为#的字符个数,
    4.if判断如果s2中#的个数等于s2的字符长度,则输出yes和s1中不为#的字符个数;如果
    s2中#的个数不等于s2的字符长度,则输出剩余的字符个数
*/
int main()
{
    string s1,s2;
    cin >> s1 >> s2;
    for(int i=0; i<s2.length(); i++)
    {
        for(int j=0; j<s1.length(); j++)
        {
            if(s2[i]==s1[j])
            {
                s1[j]='#';
                s2[i]='#';
            }
        }
    }
    int num2=0,num1=0;
    for(int i=0; i<s1.length(); i++)
    {
        if(s1[i]!='#')
            num1++;
    }

    for(int i=0; i<s2.length(); i++)
    {
        if(s2[i]=='#')
            num2++;
    }
    if(num2==s2.length())
        cout << "Yes " << num1;
    else
        cout << "No " << s2.length()-num2;
    return 0;
}

解题思路2:
1.将字符串中的字符转化成ascii码,存储到数组book中
2.设置result为0。for循环b字符串,如果根据字符对应book中的数字,如果大于0则book–,表示
相同的字符碰掉,如果不大于0,就说原来的字符中就没有或者是用光了,则result++
3.根据result判断,如果不为0,则输出no,输出result;如果为0,则输出yes,输出原来字符串-现在字符串

参考代码:

#include 
using namespace std;
int book[150];   //book默认值全为0
int main() 
{
/*
    解题思路:
    1.将字符串中的字符转化成ascii码,存储到数组book中
    2.设置result为0。for循环b字符串,如果根据字符对应book中的数字,如果大于0则book--,表示
    相同的字符碰掉,如果不大于0,就说原来的字符中就没有或者是用光了,则result++
    3.根据result判断,如果不为0,则输出no,输出result;如果为0,则输出yes,输出原来字符串-现在字符串
*/

     string a, b;
     cin >> a >> b;
     for (int i=0; i<a.length(); i++)
        book[a[i]]++;
     int result = 0;
     for (int i=0; i<b.length(); i++) 
     {
         if (book[b[i]] > 0)
            book[b[i]]--;
         else
            result++;
     }
     if(result!=0)
        printf("No %d", result);
     else
        printf("Yes %d", a.length()-b.length());
     return 0; 
}

1040
解题思路1:
1.先找第一个p,然后依次找A,最后找T,然后构建起来

参考代码:

#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int a=1000000007,num=0,o,p;
    string s;
    cin >> s;
    for(int i=0; i<s.length(); i++)
    {
        if(s[i]=='P')
        {
            o=i;
            for(int j=i+1; j<s.length(); j++)
            {
                if(s[j]=='A')
                {
                    p=j;
                    for(int k=j+1; k<s.length(); k++)
                    {
                        if(s[k]=='T')
                            num++;
                    }
                }
            }
        }
    }
    cout << num%a;
    return 0;
}

解题思路2:
1.要知道PAT的个数等于对于每一个A,A前P的个数A后T的个数累加起来即为PAT的个数
2.先循环遍历T的个数
3.for循环,若遇到P,则countp++,如果遇到A,则直接用countP
coutT累加到result,如果遇到T,则countT–,
4.最后不要忘记对1000000007求余

参考代码2:

#include 
#include 
using namespace std;
/*
    解题思路:
    1.要知道PAT的个数等于对于每一个A,A前P的个数*A后T的个数累加起来即为PAT的个数
    2.先循环遍历T的个数
    3.for循环,若遇到P,则countp++,如果遇到A,则直接用countP*coutT累加到result,如果遇到T,则countT--,
    4.最后不要忘记对1000000007求余
*/
int main()
{
     string s;
     cin >> s;
     int len=s.length(), result=0, countp=0, countt=0;
     for(int i=0; i<len; i++)
     {
         if (s[i]=='T')
         countt++;
     }
     for (int i=0; i<len; i++)
     {
         if (s[i]=='P')
            countp++;
         if (s[i] == 'T')
            countt--;
         if (s[i] == 'A')
            result=(result+(countp * countt))%1000000007;
     }
     cout << result;
     return 0;
 }

1041
解题思路1:
1.string存储一个二维数组,设置两个字符串变量s1,s2
2.输入数据,保存在数组中
3.输入整数,根据整数来对应数组中的值进行输出
参考代码1:

#include 
using namespace std;
/*
    解题思路:
    1.string存储一个二维数组,设置两个字符串变量s1,s2
    2.输入数据,保存在数组中
    3.输入整数,根据整数来对应数组中的值进行输出
*/
int main()
{
     string stu[1005][2], s1, s2;  //切记数组中的行标要超过1000
     int n, m, t;
     cin >> n;
     for(int i=0; i<n; i++) 
     {
         cin >> s1 >> t >> s2;
         stu[t][0] = s1;
         stu[t][1] = s2;
     }
     cin >> m;
     for(int i=0; i<m; i++) 
     {
         cin >> t;
         cout << stu[t][0] << " " << stu[t][1] << endl;
     }
     return 0;
 }

解题思路2:
1.用结构类型来存储,然后循环找对应的输出即可
参考代码:

#include
using namespace std;
/*
    解题思路:
    1.用结构类型来存储,然后循环找对应的输出即可
*/
struct stu
{
    long long a;
    int b;
    int c;
};
int main()
{
    int n;
    cin >> n;
    stu s[n];
    for(int i=0; i<n; i++)
        cin >> s[i].a >> s[i].b >> s[i].c;
    int m,tem;
    cin >> m;
    for(int i=0; i<m; i++)
    {
        cin >> tem;
        for(int i=0; i<n; i++)
        {
            if(s[i].b==tem)
                cout << s[i].a << " " << s[i].c << endl;
        }
    }
    return 0;
}

1042
解题思路:
1.通过getline输入一个字符串
2.定义一个数组a
3.将字符串中所有字符改成小写
4.如果是小写字符,就按照字符的ascii码,输入到数组a中
5.假设a[0]是最大值,通过循环找出,最大值,以及对应的字符

参考代码:

#include
#include
#include
#include
using namespace std;
int main()
{
    string s;
    int a[26]={0};
    getline(cin,s);
    for(int i=0; i<s.length(); i++)
        s[i]=tolower(s[i]);
    for(int i=0; i<s.length(); i++)
        if(islower(s[i]))
            a[s[i]-'a']++;
    int max=a[0],t=0;
    for(int i=1; i<26; i++)
    {
        if(a[i]>max)
        {
            max=a[i];
            t=i;
        }
    }
    printf("%c %d",'a'+t,max);
    return 0;
}

知识总结:

tolower ,toupper, isalpha, isalnum, islower,isupper
用法

#include
#include
#include
using namespace std;
int main()
{

    /*tolower将字符改成小写
    string str="THIS IS A";
    for(int i=0; i

    /*toupper将字符改成大写
    string str="this is a";
    for(int i=0; i

    /*isalpha()判断一个字符是否为子母,如果是字符返回非0,否则返会0
    cout << isalpha('2');  //返回0
    cout << isalpha('A');   返回非0
    */

    /*isalnum用来判断是否为数字或者子母,
    cout << isalnum('A'); 输出非0
    cout << isalnum('2');  输出非0
    cout << isalnum('.');  输出0
    */

    /*islower判断是否为小写字母,是,返回非0;不是,返回0
    cout << islower('a');
    cout << islower('A');
    */

    /*isupper判断是否为大写字母,是,返回非0,不是返回0
    cout << isupper('A');
    cout << isupper('a');
    */
}

1043
解题思路1:
1.首先输入字符串,将字符串中PATest对应的个数分别存放到a数组中,默认a[0]对应字符P,a[1]对应字符A…
2.用do-while循环,按照PATest的顺序输出字符,每输出一个字符个数减少1,然后循环判断是只要a数组中的数据元素一个不为
0,就循环,只到所有字符按顺序输出完,这样数组a全是0,然后就结束循环

参考代码:

#include
using namespace std;
/*
    解题思路:
    1.首先输入字符串,将字符串中PATest对应的个数分别存放到a数组中,默认a[0]对应字符P,a[1]对应字符A......
    2.用do-while循环,按照PATest的顺序输出字符,每输出一个字符个数减少1,然后循环判断是只要a数组中的数据元素一个不为
    0,就循环,只到所有字符按顺序输出完,这样数组a全是0,然后就结束循环
*/
int main()
{
    string s;
    int a[6]={0};
    char c;
    int j=0;
    cin >> s;
    for(int i=0; i<s.length(); i++)
    {
        if(s[i]=='P')
            a[0]++;
        if(s[i]=='A')
            a[1]++;
        if(s[i]=='T')
            a[2]++;
        if(s[i]=='e')
            a[3]++;
        if(s[i]=='s')
            a[4]++;
        if(s[i]=='t')
            a[5]++;
    }
  do
  {
    if(a[0]!=0)
    {
        cout << 'P';
        a[0]--;
    }

    if(a[1]!=0)
    {
        cout << 'A';
        a[1]--;
    }
    if(a[2]!=0)
    {
       cout << 'T';
       a[2]--;
    }
    if(a[3]!=0)
    {
        cout << 'e';
        a[3]--;
    }
    if(a[4]!=0)
    {
        cout << 's';
        a[4]--;
    }
    if(a[5]!=0)
    {
        cout << 't';
        a[5]--;
    }

  }while(a[0]!=0 || a[1]!=0 || a[2]!=0 || a[3]!=0 || a[4]!=0 || a[5]!=0);

    return 0;
}

解题思路2:
1.用cin.get()将字符串中的字符保存到其ASCII码下标的数组中
2.用while+if进行循环

参考代码:

#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     int map[128]={0},c;
     while ((c = cin.get()) != EOF)   //表示没有到文件的结尾,判题的时候输入一个样例,就是到文件的结尾了
        map[c]++;
     while (map['P'] > 0 || map['A'] > 0 || map['T'] > 0 || map['e'] > 0 ||map['s'] > 0 || map['t'] > 0)
     {
         if (map['P']-- >0)     //对于map['P']-- >0是先比较后自减,对于--map['P'] >0 是先自减后比较
            cout << 'P';
         if (map['A']-- >0)
           cout << 'A';
         if (map['T']-- >0)
           cout << 'T';
         if (map['e']-- >0)
           cout << 'e';
         if (map['s']-- >0)
           cout << 's';
         if (map['t']-- >0)
           cout << 't';
     }
     return 0;
 }

1044
解题思路:
1.还是用字符串数组保存参数
2.设置void func1和void func2函数分别表示将数字转换为火星文,将火星文转化为数字
3.对于func1而言:
1.对于t/13的除数放到b数组中查找
2.如t/13和t%13均不为0,则输出“ ”
3.对于t%13的数在a数组中查找,同时也要对t为0时,是在a数组中找
4.对于func2而言:
1.将str中0–2中的字符串赋值出来,如果字符串长度大于4,则将4–6字符串复制出来
2.for循环从1开始对于13以内的数字则s1==a[j]或者大于13则s2=a[j]
3.对于s1再在b数组中找,返回t1*13+t2;

参考代码:

#include 
#include 
#include
using namespace std;
/*
    1.还是用字符串数组保存参数
    2.设置void func1和void func2函数分别表示将数字转换为火星文,将火星文转化为数字
    3.对于func1而言:
        1.对于t/13的除数放到b数组中查找
        2.如t/13和t%13均不为0,则输出“ ”
        3.对于t%13的数在a数组中查找,同时也要对t为0时,是在a数组中找
    4.对于func2而言:
        1.将str中0--2中的字符串赋值出来,如果字符串长度大于4,则将4--6字符串复制出来
        2.for循环从1开始对于13以内的数字则s1==a[j]或者大于13则s2=a[j]
        3.对于s1再在b数组中找,返回t1*13+t2;
*/
string a[13] = {"tret", "jan", "feb", "mar", "apr", "may", "jun", "jly", "aug","sep", "oct", "nov", "dec"};
string b[13] = {"####", "tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo","syy", "lok", "mer", "jou"};
//将字符串和长度len设置为全局变量,这样方便调用函数时,不用传入过多的参数
string s;       
int len;

void func1(int t)
{
 if (t/13)
    cout << b[t/13];
 if ((t/13) && (t%13))
    cout << " ";
 if (t%13 || t==0)
    cout << a[t%13];
}

void func2()
{
     int t1=0, t2=0;
     string s1=s.substr(0,3),s2;   //substr复制字符串的函数
     if (len>4)
        s2 = s.substr(4,3);
     for (int j = 1; j <= 12; j++)
     {
         if (s1==a[j] || s2==a[j])    //为啥要填入s1=a[j]? 答:对于13进制以内的数有用,如feb=5;
            t2=j;
         if (s1==b[j])
            t1=j;
     }
     cout << t1*13+t2;
 }

int main()
{
     int n;
     cin >> n;
     getchar();         //清除缓冲区的回车字符,注意以后在循环外和内中都要输入时,不要忘记加上getchar()消除缓冲区的字符
     for (int i = 0; i < n; i++)
     {
         getline(cin, s);
         len=s.length();
         if (s[0]>='0' && s[0]<='9')
            func1(stoi(s));
         else
            func2();
         cout << endl;
     }
     return 0;
 }

注意事项:
1.清除缓冲区的回车字符,注意以后在循环外和内中都要输入时,不要忘记加上getchar()消除缓冲区的字符
2.注意格式,在主函数中每次循环一次输出endl,但在自身的输入时不要加endl

知识总结:
stoi(将数字字符串改为整数)+ s.substr(pos,n)(将字符串中的字符复制到另一个字符串中)

#include
#include
using namespace std;
int main()
{/*
    string str="abcdef";
    string a=str.substr(0,11);
    cout << a;

0. 用途:一种构造string的方法

1. 形式:s.substr(pos, n)

2. 解释:返回一个string,包含s中从pos开始的n个字符的拷贝(pos的默认值是0,n的默认值是s.size() - pos,即不加参数会默认拷贝整个s)

3. 补充:若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾*/

/*字符串转化整数函数
    string s="123";
    cout << stoi(s);
    */
}

1045
解题思路1:
解题思路:
1.设置三个数组:abv分别表示原始数组,sort排列后的数组,主元元素数组
2.核心思路,找a与b数组中相同的数字,并且该数字大于前的最大值,因为如果a与b的某个数字相同,说明后面的元素
都比该元素大,故只用说明该数字大于之前的最大值即可
3.输出数组v
注意事项:
1.输出主元元素的个数时,要换行
2.最后整个数组输出完后,加换行

参考代码:

#include
#include
#include
using namespace std;
int v[1000000];
int main()
{
    int n,max=-1,cnt=0;
    cin >> n;
    vector<int> a(n),b(n);
    for(int i=0; i<n; i++)
    {
        cin >> a[i];
        b[i]=a[i];
    }
    sort(a.begin(),a.end());
    for(int i=0; i<n; i++)
    {
        if(a[i]==b[i] && b[i]>max)
        {
            v[cnt++]=b[i];
        }

        if(b[i]>max)
            max=b[i];
    }
    cout << cnt << endl;
    for(int i=0; i<cnt; i++)
    {
        if(i!=0)
            cout << " ";
        cout << v[i];
    }
    cout << endl;
    return 0;
}

解题思路2;
1.主元的判断条件:左边元素都比其小,右边的元素都比其大,或者换句话说,如果左边的某个数比其大或者右边的某个数比其小,则
不是主元
2.可以将合适的数组放到数组中,最后排序输出

参考代码:

#include
#include
using namespace std;
/*

*/
int main()
{
    int n,num=0;
    cin >> n;
    int a[n],b[n];
    for(int i=0; i<n; i++)
    {
        cin >> a[i];
        b[i]=a[i];
    }

    sort(a,&a[n]);
    for(int i=0; i<n; i++)
    {
        if(a[i]==b[i])
            num++;
    }
    cout << num << endl;
    for(int i=0; i<n; i++)
    {
        if(a[i]==b[i])
        {
            if(i!=0)
                cout << " ";
            cout << a[i];
        }
    }
    return 0;
}

1046
解题思路:
1.设置四个,jiahan,jiahua,yihan,yihua, jiahe,yihe
2.逻辑如下

参考代码:

#include
using namespace std;
/*

*/
int main()
{
    int n;
    cin >> n;
    int jiahan,jiahua,yihan,yihua,jiahe=0,yihe=0;
    for(int i=0; i<n; i++)
    {
        scanf("%d %d %d %d",&jiahan,&jiahua,&yihan,&yihua);
        if(jiahua==jiahan+yihan && jiahua!=yihua)
            yihe++;
        if(yihua==jiahan+yihan && jiahua!=yihua)
            jiahe++;


    }
        cout << jiahe << " " << yihe << endl;
    return 0;
}

1047
解题思路:
1.必然有使用scanf输入
2.完全可以将最后成绩保存在队伍编号的数组中

参考代码:

#include
using namespace std;
/*

*/

int main()
{
    int n,duiwu,duiyuan,chengji,maxduiwu=0;
    cin >> n;
    int a[1001]={0};
    for(int i=0; i<n; i++)
    {
        scanf("%d-%d %d",&duiwu,&duiyuan,&chengji);
        a[duiwu]+=chengji;
    }
    for(int i=0; i<1001; i++)
    {
        if(a[i]>a[maxduiwu])
            maxduiwu=i;
    }
    cout << maxduiwu << " " << a[maxduiwu];
    return 0;
}

1048
解题思路:
1.将a,b字符串倒转过来
2.根据比较字符串长度,给较短位补0
3.设置str保存0,1…J,Q,K
4.对于原来的数位而言,从个位开始就是奇数位,下一位就是偶数位,如果倒转过来,第一位虽然是偶数位,但是
还是执行的是原来奇数位的操作。
5.每次循环时将计算结果累加到字符串c中,最后倒叙输出

参考代码:

#include
#include
using namespace std;
int main()
{
    string a,b,c;
    string str="0123456789JQK";
    cin >> a >> b;
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());

    if(a.length()>b.length())
        b.append(a.length()-b.length(),'0');
    else
        a.append(b.length()-a.length(),'0');

    for(int i=0; i<b.length(); i++)
    {
        if(i%2==0)
            c+=str[(b[i]-'0'+a[i]-'0')%13];
        else
        {
            int tem=b[i]-a[i];
            if(tem<0)
                tem+=10;
            c+=str[tem];       //由于对应的数字位相减,所以最大差值为9,而c是字符串,所以也可以直接用str[tem]来连接
        }
    }
    for(int i=c.length()-1; i>=0; i--)
        cout << c[i];
    return 0;
}

知识总结:
1.a.append(n,c)表示对字符串a的尾部添加n个字符c
2.reverse(a.begin(),a.end()) 对字符串a进行倒转

1049
解题思路:
1.通过找规律,其实就是每个数字出现i*(n-i+1)次,
2.规律如下图:

参考代码:

#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int n;
    cin >> n;
    double sum=0.0,tem;
    for(int i=1; i<=n; i++)
    {
        cin >> tem;
        sum+=tem*i*(n-i+1);
    }
    printf("%.2f",sum);
}

pat乙级1001,1002_第8张图片

解题思路:
1.先求合适的m,n
2.定义一个vector数组,并对其进行递减排序
3.用vector定义一个二维数组
4.用如下图的双循环,对二维数组赋值(设置原始数组a中的变量为t=0,依次将a数组中的值放到合适的二维数组位置,不要忘记t 1.外层循环是以口字型顺时针循环,规律是根据行数m,通过找规律得出level=m/2+m%2
2.对于每一个外层循环来说,又有4个内层循环,分别是左上到右上、右上到右下、右下到左下、左下到左上的顺序⼀层层填充
5.用双层for循环输出二维数组,对j!=n-1的话,则输出空格保证最后一个数字没有多余的空格
pat乙级1001,1002_第9张图片
餐考代码:

#include 
#include 
#include 
#include 
using namespace std;


/*
    解题思路:

*/

int cmp(int a, int b)
{
    return a > b;
}

int main()
{
     int N, m, n, t = 0;
     scanf("%d", &N);

     /*
        题中要求m-n的值是所有可能值中最小的,m>=n; m*n=N。所以对于n取根号下N然后取整就表示想让
        n与m值最接近,此时n的值一定小于等于N开根号也就满足m>=n,递减循环,如果有N整除n,则m=N/n,退出循环
     */
     for (n=sqrt(N); n>=1; n--)
     {
         if (N%n==0)
         {
             m=N/n;
             break;
         }
     }

     vector<int> a(N);
     for (int i=0; i<N; i++)
        cin >> a[i];

     sort(a.begin(), a.end(), cmp);  //对数组递减排序

     /*
     用vector初始化一个元素全为0的数组
     定义了一个vector容器,元素类型为vector,初始化为包含m个vector对象,
     每个对象都是一个新创立的vector对象的拷贝,
     而这个新创立的vector对象被初始化为包含n个0。
     */
     vector<vector<int> > b(m, vector<int>(n));

     
     /*
        层数就是通过找规律得出,m为奇数,外层数是m/2+1;m为偶数,外层数就是m/2 则m=m/2+m%2
     */
     int level=m/2+m%2;
     
     for (int i=0; i<level; i++)
     {
         /*
            第一个循环是从左上到右上,
         */
         for (int j=i; j<n-i && t<N; j++)
            b[i][j] = a[t++];
            
        /*
            第2个循环是从右上到右下
        */
         for (int j=i+1; j<m-1-i && t < N; j++)
            b[j][n - 1 - i] = a[t++];

        /*
            第3个循环是从右下到左下
        */
         for (int j=n-i-1; j>=i && t<N; j--)
            b[m-1-i][j] = a[t++];
        /*
            第4个循环是从左下到左上
        */
         for (int j=m-2-i; j>=i+1 && t<N; j--)
            b[j][i] = a[t++];
     }
     
     for (int i = 0; i < m; i++)
     {
         for (int j=0 ; j<n; j++)
         {
             printf("%d", b[i][j]);
             if (j != n - 1)
                printf(" ");
         }
         printf("\n");
     }
     return 0;
 }

知识总结:
1.用vector将数组按照递减排序

#include
#include
#include
int cmp(int a, int b)
{
    return a > b;
}

int main()
{
	vector<int> a;
	sort(a.begin(),a.end(),cmp);
}

2.用vector设置二维数组
用vector初始化一个元素全为0的数组
定义了一个vector容器,元素类型为vector,初始化为包含m个vector对象,
每个对象都是一个新创立的vector对象的拷贝,
而这个新创立的vector对象被初始化为包含n个0。

     vector<vector<int> > b(m, vector<int>(n));

1051
解题思路:
1.通过极坐标的形式进行复数相乘,如下图
2.对于特殊情况,比如A=-0.0001,如果直接保留2位小数,则为-0.00而非0.00,而这种情况,只针对A<0且A+0.005>0
3.对于B有三种情况,大于等于0是直接输出;与A类似的一种情况;B小于0并且B小于-0.005
pat乙级1001,1002_第10张图片
参考代码:

#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main() 
{
     double r1, p1, r2, p2, A, B;
     cin >> r1 >> p1 >> r2 >> p2;
     A = r1 * r2 * cos(p1) * cos(p2) - r1 * r2 * sin(p1) * sin(p2);
     B = r1 * r2 * cos(p1) * sin(p2) + r1 * r2 * sin(p1) * cos(p2);
     if (A + 0.005 > 0 && A < 0)
        printf("0.00");
     else
        printf("%.2f", A);
        
     if(B >= 0)
        printf("+%.2fi", B);
     else if (B + 0.005 > 0 && B < 0)
        printf("+0.00i");
     else
        printf("%.2fi", B);
     return 0; 
 }

1052
解题思路:
1.将输入样例,转化为字符数组
2.按照要求输出

参考代码:

#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     //

     /*
        1.定义一个字符串的二维数组v(有3行)
        2.使用getline接受字符串
        3.设置两个循环变量j,k分别表示[和]的位置
        4.用双层while-if嵌套将表情放到row(row表示一行表情字符串)中,再将row放到v中
     */
     vector<vector<string>> v;

     for(int i=0; i<3; i++)
     {
         string s;
         getline(cin,s);
         vector<string> row;    //定义一个字符数组
         int j=0, k=0;
         while(j < s.length())
         {
             if(s[j] == '[')
             {
                 /*
                    k直接在此处自增是因为,如果第一次k走到]这个位置,if判断为真,压入栈,退出循环,其实
                    k已经走到下一个位置也就是下一个[处,如果将k放到if后面自增的话,那么k的值一直不变。
                 */
                 while(k++ < s.length())
                 {
                     if(s[k] == ']')
                     {
                         row.push_back(s.substr(j+1, k-j-1));
                         break;
                     }
                 }
             }
             j++;
         }
         v.push_back(row);
     }

     int n;
     cin >> n;
     for(int i = 0; i < n; i++)
     {
         int a, b, c, d, e;
         cin >> a >> b >> c >> d >> e;
         /*
            如果这里输入的数字,大于字符数组中字符元素的长度的话,输出Are you kidding me? @\/@,由于每个
            字符串都是从1开始,所以如果输出0,也是选择的序号不存在,就输出Are you kidding me? @\/@
         */
         if(a>v[0].size() || b>v[1].size() || c>v[2].size() || d>v[1].size() || e>v[0].size() || a<1 || b<1 || c<1 || d<1 || e<1)
         {
             cout << "Are you kidding me? @\\/@" << endl;
             continue;
         }
         cout << v[0][a-1] << "(" << v[1][b-1] << v[2][c-1] << v[1][d-1] << ")" << v[0][e-1] << endl;
     }
     return 0;
 }

知识总结:
1.用vector嵌套一个字符串数组

vector<vector<string>> v;

2.用getline接受一个字符串

getline(cin,s);

3.给字符串压栈

s.push_back(a);  //将字符串a压栈到s中

4.截取字符串

s.substr(k,j);   //表示在s字符串中,第k个位置,一共截取j个字符

法are

1053
解题思路:
1.设置knkz,kz,
2.利用双层for比较:N,e,D,a 先比较电量是否高于观察期的一半,如果高于,则再判断是否大于指定的天数,计算
出knkz和kz的个数,最后再求百分比后输出

参考代码:

#include
#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    /*
        注意事项:
        1.对“可能控制”,“控制”的判断,先if判断是否存在超过一半的日子用电量低于某给定的阈值e,然后用一个
        ?:进一步判断是否观察期超过某给定阈值 D 天,然后选择是对knkz自增还是kz自增
        2.输出%时,应该输出两个%
    */
    int N,D,a;
    double e,knkz=0.0,kz=0.0;
    double temp=0.00;
    cin >> N >> e >> D;
    for(int i=0; i<N; i++)
    {
        cin >> a;
        int tempcount=0;
        for(int j=0; j<a; j++)
        {
            cin >> temp;
            if(temp<e)
                tempcount++;
        }
        if(tempcount>a/2)
        {
            a>D?kz++:knkz++;
        }
    }
    printf("%.1f%% %.1f%%",knkz/N*100,kz/N*100);
    return 0;
}

注意事项:
1.对“可能控制”,“控制”的判断,先if判断是否存在超过一半的日子用电量低于某给定的阈值e,然后用一个
?:进一步判断是否观察期超过某给定阈值 D 天,然后选择是对knkz自增还是kz自增
2.输出%时,应该输出两个%

1054
解题思路:
1.用字符数组来存放输入的值
2.不管a是啥,都将a转化为浮点型的数放到临时变量temp中
1.对于整数,实数而言,直接将字符类型转化为双精度浮点数
2.对于字母串而言,转化成的双精度浮点数是一个极小的数,比如aaa,转化为7.98855e-305
3.对于有多个小数点而言,只取到第2个小数点之前
3.在将temp保留2位小数,放到字符数组中,以a的长度为基准,遍历循环如果,a[i]!=b[i]则flag=1
4.如果flag=1或者temp<-1000 或者temp>1000,则输出:ERROR: aaa is not a legal number
5.否则累加temp,并记录个数
6.如果个数为1,则直接输出sum;如果个数为0,则输出undefined,否则输出:The average of 3 numbers is 1.38

参考代码:

#include
#include
#include
using namespace std;
int main()
{
    char a[50],b[50];
    double sum=0.0,temp=0.0;
    int n,cnt=0;
    cin >> n;
    for(int i=0; i<n; i++)
    {
        scanf("%s",a);
        sscanf(a,"%lf",&temp);
        sprintf(b,"%.2f",temp);

        int flag=0;

        for(int j=0; j<strlen(a); j++)      //对于字符数组而言,用strlen去求其长度
            if(a[j]!=b[j])
                flag=1;

        if(flag || temp<-1000 || temp>1000)
        {
            cout << "ERROR: " << a <<  " is not a legal number" << endl;
            continue;
        }

        else
        {
            sum+=temp;
            cnt++;
        }
    }
    //根据上面cnt的结果,输出对于字符串,而不是对于每个字符串都要输出平均值结果
        if(cnt==1)
            printf("The average of 1 number is %.2f\n",sum);  //对于只有一个值时,直接输出sum,并且保留2位小数
        else if(cnt>1)
            printf("The average of %d numbers is %.2f\n", cnt, sum / cnt);  //printf不能与endl结合
        else
            cout << "The average of 0 numbers is Undefined" << endl;
        return 0;

}

知识总结:
1.将字符数组a以浮点数的方式保存到temp中

 sscanf(a, "%lf", &temp);  //将a以浮点型的方式放到temp中

2.将temp变量以保留2位小数的方式输出到字符数组b中

char a[50], b[50];
sprintf(b, "%.2f",temp);

注意事项:
1.后面的if-else是对于输出平均值的字符串,共3中情况:
1.只有1个值时,则直接输出sum,保留2位小数
2.没有值时,则直接输出The average of 0 numbers is Undefined
3.如果cnt>1则,输出sum/cnt,并保留2位小数即可

1055
解题思路:
1.用结构数组来存储人名和身高
2.自定义一个cmp,如果身高不同的话,则按身高降序排列(对于输出是先输出最后一排,所以按照降序排列),身高相同按照名字的升序排列,对结构数组进行排序
3.设置两个边t,row分别表示:t表示结构数组中,按照n/k分配好的第一个下标,row表示行树,初值分别为0,k
4.如果row==k,则让m=n-n/k*(k-1)表示最后一行人数,如果row!=k,则m=n/k表示每行的人数
5.定义一个字符串数组ans,来存放人名。从按照n/k划分好的结构数组中将人名放到ans中,当然先一次性放完左边合适的人名,然后
再一次性放完右边合适的人名
6.按照输出要求输出这一排人名
7.不要忘记row–,t+=m

参考代码:

#include 
#include 
#include 
using namespace std;
/*
    解题思路:

*/

//设置一个结构
struct node 
{
     string name;
     int height;
};

//设置一个cmp,用:?来表示,如果身高不同的话,则按降序排列,身高相同按照名字的升序排列
int cmp(struct node a, struct node b) 
{
    return a.height != b.height ? a.height > b.height : a.name < b.name; 
}

int main() 
{
     int n, k, m;
     cin >> n >> k;
     
     //用vector来定义一个结构数组
     vector<node> stu(n);
     
     for(int i = 0; i < n; i++) 
     {
         cin >> stu[i].name;
         cin >> stu[i].height;
     }
     
     sort(stu.begin(), stu.end(), cmp);
     
     int t = 0, row = k;
     
     while(row) 
     {
         if(row == k)   //对于最后一排而言,肯定要先输出,然后依次是n/k的个数,m表示每排的人数
         {
            m = n-n / k * (k - 1);
         } 
        else 
          {
            m = n / k;
          }
        
        //定义一个字符串数组,表示每排的人名
         vector<string> ans(m);
         
         //t初值是0,又因为结构数组,按照身高降序排列,名字升序排列,所以stu[t].name就表示身高在这排中最大的人名,ans[m/2]=stu[t].name就是把每排中身高最大的人放到中间
         //t在样例中的值分别是0,4,7,t表示结构数组中,按照n/k分配的第一个下标
         ans[m / 2] = stu[t].name;
         
         // 左边⼀列
         /*
            1.j是人名字符串数组ans的变量,i是结构数组stu的变量
            2.j=m/2-1,表示从紧靠中间的左边开始
            3.对于for含义是一次直接将左边合适的人名全部输出,所以变量i是递增2
                1.i=t+1; 表示从按照划分的结构数组中的第2个位置开始,都放在左边
    
         */
         int j = m / 2 - 1;
         for(int i = t + 1; i < t + m; i = i + 2)
            ans[j--] = stu[i].name;
            
         // 右边⼀列
         /*
            1.j=m/2+1; 表示从紧靠中间的右边开始
            2.i从t+2开始,表示从按照划分的结构数组中的第3个位置开始,都放在右边
         */
         j = m / 2 + 1;
         for(int i = t + 2; i < t + m; i = i + 2)
            ans[j++] = stu[i].name;
            
         // 输出当前排
         cout << ans[0];
         for(int i = 1; i < m; i++)
            cout << " " << ans[i];
         cout << endl;
         t = t + m;
         row--;
     }
     return 0; 
 }

知识总结:
1.自定义cmp,对结构数组进行排序

struct node
{
    string name;
    int tall;
};

int cmp(node a,node b)  //是对结构进行排序,所以必须定义两个结构node类型的变量a,b。函数类型还是int。如果身高不同按照降序排列,否则按照名字的升序排列
{
    return a.tall!=b.tall?a.tall>b.tall:a.name<b.name;
}
int main()
{
    int m,n,k;
    cin >> n >> k;
    vector<node> stu(n);
    for(int i=0; i<n; i++)
        cin >> stu[i].name >> stu[i].tall;
    sort(stu.begin(),stu.end(),cmp);
    
}

1056
解题思路:
1.通过观察,可知sum+=a[i] * 11 * (n-1)

参考代码:

#include
using namespace std;
int main(){
    int n,sum=0;
    cin >> n;
    int a[n];
    for(int i=0; i<n; i++){
        cin >> a[i];     
        sum+=a[i]*11*(n-1);           
    }
    cout << sum;
    return 0;
}

1057
解题思路1:
1.先计算字符串中字母的所代表值的和
2.对其进行2进制计算,同时计算1,0的个数

参考代码1:

#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    string s;
    getline(cin,s);
    int sum=0,temp,ycount=0,lcount=0;
    for(int i=0; i<s.size(); i++)
    {

        if('a'<=s[i] && s[i]<='z')
            temp=s[i]-'a'+1;
        else if('A'<=s[i] && s[i]<='Z')
            temp=s[i]-'A'+1;
        else
            continue;
        sum+=temp;
    }
    while(sum!=0)
    {
        if(sum%2)
            ycount++;
        else
            lcount++;
        sum/=2;
    }
    cout << lcount << " " << ycount;

    return 0;
}

解题思路2:
1.用getline输入一个字符串
2.通过for循环,首先用isalpha判断是否为字母,若是,用toupper将字母改为大写字母,然后累加
3.统计n为2进制时,0和1的个数

参考代码:

#include
#include
using namespace std;
int main()
{
    string s;
    getline(cin,s);
    int n=0;
    for(int i=0; i<s.length(); i++)
        if(isalpha(s[i]))
        {
            s[i]=toupper(s[i]);
            n+=(s[i]-'A'+1);
        }
    int cnt0=0,cnt1=0;
    while(n!=0)
    {
        if(n%2==0)
            cnt0++;
        else
            cnt1++;
        n/=2;
    }
    cout << cnt0 << " " << cnt1;
    return 0;
}

知识总结:
1.
isalpha()判断ch是否为英文字母,若是英文字母返回非0(小写字母为2,大写字母为1)
2.toupper()函数是将小写字母转化为大写字母

1058
1.解题思路:
1.vector right(m)表示标准答案的二维数组,vector total(m), wrongCnt(m);
分别表示每道题的满分情况,每道题错误次数
2.第一个双层for:输入题目的情况
1.外层for控制m个题的循环
2.内存for根据输入标准答案选项的个数,输入到二维数组right中
3.第二个三层for:输入学生的答题情况,以及输出每个学生的成绩
1.外层for控制n个人
2.内存for控制每个人答m个题的情况
3.最内层for根据(后的数字,往set类型的st中insert学生的具体答案
4.第3个for找出错得最多的题目的错误次数
5.if-else:
如果错误次数为0,输出too simple
否则循环遍历题目,如果本题的错误次数与max一致,则输出i+1表示题号

2.参考代码:

#include 
#include 
#include 
#include 
using namespace std;
/*
    解题思路:

            
    注意事项:
    1.每道题的选项个数就是一个形同虚设的值,直接用temp保存,没有实际用处
    2.特别注意第二个三层for中,scanf("\n")的使用
                                 
                                 
    知识总结:
    1.set类型的变量,只能用inset输入

            
        
*/
int main()
{
     int n, m, temp, k;
     cin >> n >> m;
     vector<set<char>> right(m);   //用二维数组存放正确选项
     vector<int> total(m), wrongCnt(m);  //用int数组存放满分

     //输入题目的信息
     for(int i = 0; i < m; i++)
     {
         cin >> total[i] >> temp >> k;   //total表示满分,temp表示题目个数,k表示是正确选项个数

         //输入正确选项
         for(int j = 0; j < k; j++)
         {
             char c;
             cin >> c;
             right[i].insert(c);   //想要往set中插入值,必须使用insert
         }
     }

    //输入学生的答题情况
    /*

        2.为啥没(的输入?
           仔细看41行中有没(
    */
     for(int i = 0; i < n; i++)
     {
         int score = 0;
         scanf("\n");    //为了避免下一次的scanf直接读取\n而结束,保证每次都等待键盘输入……,也可以写成getchar()
         for(int j = 0; j < m; j++)     //这里是输入每一行中答题内容
         {
             if(j != 0)
                scanf(" ");    //用法和scanf("\n"); 一个意思
             scanf("(%d", &k);   //输入每个括号内有多少个答案
             set<char> st;
             char c;

             for(int l = 0; l < k; l++)   //将每个括号中的答案放到set中
             {
                 scanf(" %c", &c);
                 st.insert(c);
             }

             scanf(")");   //接受一个反括号

             if(st == right[j])    //如果括号中的答案和题目信息中的答案匹配,则该题为满分
             {
                score += total[j];
             }
            else
             {
                wrongCnt[j]++;   //如果答案不对,则记录该题错误的个数  记录每道题的错误个数
             }
         }
         printf("%d\n", score);
     }


     int maxWrongCnt = 0;       //设置一个最大变量
     
     for(int i = 0; i < m; i++)        //找出错得最多的题目的错误次数
     {
         if(wrongCnt[i] > maxWrongCnt)
         {
            maxWrongCnt = wrongCnt[i];
         }
     }

     if(maxWrongCnt == 0            //如果错得最多的题目的错误次数为0,输出Too simple
        printf("Too simple"); 
     else                               //首先输出错得最多的题目的错误次数,如果本题的错误次数和maxWrongCnt一致,则输出i+1
     {
         printf("%d", maxWrongCnt);
         
         for(int i = 0; i < m; i++)
         {
             if(wrongCnt[i] == maxWrongCnt)
             {
                printf(" %d", i + 1);
             }
         }
     }
     return 0;
 }

3.知识总结
1.关于scanf("\n")与scanf(" ")的讨论

#include 
#include 
using namespace std;
int main()
{
     int n,k=3;
     cin >> n;
     /*
         此代码的含义是:
         1.输入一个n,然后循环输入(k1 (k2 (k3 .... 并输出k1 k2 k3
     */
     for(int i = 0; i < n; i++)
     {
        scanf("\n");    //吃掉上面那个输入n时的回车,加入此行代码,只针对于输入带有符号的输入
        scanf("(%d", &k);  
        cout << k << endl;

     }
     return 0;
}

运行结果:

pat乙级1001,1002_第11张图片
2.关于set类型的用法:

#include
#include
using namespace std;
int main()
{
    set<int> s;
    set<int>::iterator its;   //设置一个迭代器
    int temp,n;
    cin >> n;
    
     
    for(int i=0; i<n; i++)   //只能以insert的方式插入数字
    {
        cin >> temp;
        s.insert(temp);
    }
    
    
    for(its=s.begin(); its!=s.end(); its++)   //使用迭代的方式读取数字
        cout << *its;


    return 0;
}

注意事项:
1.每道题的选项个数就是一个形同虚设的值,直接用temp保存,没有实际用处
2.特别注意第二个三层for中,scanf("\n")的使用

3.如果不加循环中scanf("\n")运行结果:

pat乙级1001,1002_第12张图片

原因是:
在输入完n后,会敲一个回车,这个回车\n进入缓冲区,而scanf遇到(空格,制表符,回车)会自动结束,所以不理下面的scanf("(%d",&k),空白区中一直有\n,所以每次循环scanf一遇到\n就结束,则一直输出3。若加上scanf("\n"),则回车时将\n吃掉,所以重新正常输入,然后输出,在进入下一次循环时,scanf("\n")还是会吃掉上一次输入完后的\n

pat乙级1001,1002_第13张图片

如果这样写,当max为0时,则输出完Too simple 后还要输出00000
所以一定要将for写入else中

1059
解题思路:

2.先输出学号,用printf,用%04d,占4位输出,不足为数左端补0
3.如果ran[id]==0表示id根不不在排名里,输出Are you kidding?
4.设置set类型的集合ss,ss保存的是id号,先在ss中寻找id是否存在,是,就输出checked 不是,就把数字插进去
5.如果ran[id]==1,输出Mystery Award
6.然后排名是素数,输出Minion
7.其余输出Chocolate

参考代码:

#include
#include
using namespace std;

bool sushu(int a)
{
    if(a<=1)
        return false;
    for(int i=2; i<a; i++)
        if(a%i==0)
            return 0;
    return 1;
}

int main()
{
    int n;
    cin >> n;
    int ran[10000],id;
    for(int i=0; i<n; i++)
    {
        cin >> id;
        ran[id]=i+1;
    }

    int m;
    cin >> m;
    set<int> ss;
    for(int i=0; i<m; i++)
    {
        cin >> id;
        printf("%04d: ",id);
        if(ran[id]==0)
        {
            cout << "Are you kidding?" << endl;
            continue;
        }

        if(ss.find(id)==ss.end())
            ss.insert(id);
        else
        {
            cout << "Checked" << endl;
            continue;
        }


        if(ran[id]==1)
            cout << "Mystery Award" << endl;
        else if(sushu(ran[id]))
            cout << "Minion" << endl;
        else
            cout << "Chocolate" << endl;

    }
    return 0;
}

知识总结:
1.set中的find
if( ss.find(id) == ss.end() ) //表示ss中没有找到id这个值

1060
解题思路:
1.一般的思路肯定是,从骑行的最大公里开始,看是否有E天超过E公里,从大到小开始寻找
2.此题的思路是以E天为准,从1开始,将每天的骑行距离按照降序排列,从下标为1开始
3.a[p]>p:当p=1时,表示肯定有1天超过1公里;当p=2时,表示肯定有2天超过2公里;当p=3时,表示肯定有3天
超过3公里…一直循环到a[p]<=p此时就表示,当天的距离没有超过p,则E就是上一个值,也就是为啥ans表示E从0
开始,p从1开始,结果E就是ans

#include
#include
#include
using namespace std;

bool cmp(int a,int b)
{
    return a>b;
}

int main()
{
    int n;
    cin >> n;
    int a[n+1];
    for(int i=1; i<=n; i++)
        cin >> a[i];
    sort(a+1,a+n+1,cmp);

    int ans=0,p=1;
    while(ans<=n && a[p]>p)
    {
        ans++;
        p++;
    }
    cout << ans;
    return 0;
}

1061
解题思路:
1.设置3个数组manfen,biaoda,xueda
2.先输入进去manfen,biaoda
3.双层for循环,输入学生答案,与biaoda对比,如果一样则sum累加manfen,循环完后输出

参考代码:

#include
#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int n,m;
    cin >> n >> m;
    int manfen[m],biaoda[m],xueda[m];
    for(int i=0; i<m; i++)
        cin >> manfen[i];
    for(int i=0; i<m; i++)
        cin >> biaoda[i];

    for(int i=0; i<n; i++)
    {
        int sum=0;
        for(int j=0; j<m; j++)
        {
            int temp;
            cin >> temp;
            if(temp==biaoda[j])
                sum+=manfen[j];
        }
        cout << sum << endl;
    }
    return 0;
}

1062
解题思路1:
1.先找M1,M2的最小公倍数S1,然后在找S1与K的最小公倍数K1
2.通分,将N1变为L1,将N2变为L2
3.找L1~L2之间找K1/K的倍数
4.写一个将分数化为最简分数的函数huajian,对于上面所有找的值进行化简,判断其分母是否为K,是则输出;不是
则不输出

参考代码:

#include
#include
using namespace std;
/*
    解题思路:

*/
int zuiyin(int a,int b)
{

    int max=-1;

    if(a>b && a%b==0)
        return b;
    else if(a<b && b%a==0)
        return a;
    int temp=a>b?b:a;
    for(int i=1; i<temp; i++)
    {
        if(a%i==0 && b%i==0)
            if(i>max)
                max=i;
    }
    return max;
}
int main()
{
    int N1,N2,M1,M2,L1,L2,K;
    scanf("%d/%d %d/%d %d",&N1,&M1,&N2,&M2,&K);
    int S1=M1*M2/zuiyin(M1,M2);
    int K1=K*S1/zuiyin(S1,K);
    L1=K1/M1*N1;
    L2=K1/M2*N2;
    int flag=0;
    for(int i=L1+1; i<L2; i++)
        if(i%(K1/K)==0)
            if(zuiyin(i,K1)==K1/K)
            {
                if(flag!=0)
                    cout << " ";
                printf("%d/%d",i/(K1/K),K);
                flag++;
            }
    return 0;
}

解题思路2;
1.不用找M1,M2,K的最大公约数。
2.用分母相乘的方法,先找到 num/K 比N1/M1大的最小num
3.用while循环,也是用分母相乘的方法,找到所有num/k 小于 N2/M2,同时判断num与k之间的最大公约数是否为1
是就输出
4.详见如下图
pat乙级1001,1002_第14张图片

参考代码:

#include
using namespace std;

int gcd(int a, int b)
{
    return b==0?a:gcd(b,a%b);
}


int main()
{
    int n1,m1,n2,m2,k;
    scanf("%d/%d %d/%d %d",&n1,&m1,&n2,&m2,&k);

    if(n1*m2>m1*n2)
    {
        swap(n1,n2);
        swap(m1,m2);
    }

    int num=1;
    while(n1*k>=m1*num)
        num++;
    int flag=0;
    while(num*m2<k*n2)
    {
        if(gcd(num,k)==1)
        {
            if(flag!=0)
                cout << " ";
            printf("%d/%d",num,k);
            flag++;
        }
        num++;
    }
    return 0;
}

知识总结:
1.求最大公约数—辗转相除法

int gcd(int a, int b)
{
    return b==0?a:gcd(b,a%b);
}

1063
解题思路:
过于简单,没有思路

参考代码:

#include
#include
#include
using namespace std;

int main()
{
    double max=-1.0,temp,temp1,temp2;
    int n;
    cin >> n;
    for(int i=0; i<n; i++)
    {
        cin >> temp1 >> temp2;
        temp=sqrt(temp1*temp1+temp2*temp2);
        if(temp>max)
            max=temp;
    }
    printf("%.2f",max);
    return 0;
}

1064
解题思路:
1.对于每一个输入的数字,求其每个位上的数字和
2.将其insert入set类型a中

参考代码:

#include
#include
using namespace std;
/*
    解题思路:

    

*/
int main()
{
    int n;
    cin >> n;
    int flag=0;
    set<int>a;
    set<int>::iterator ita;
    for(int i=0; i<n; i++)
    {
        int temp;
        cin >> temp;
        int num=0;
        while(temp!=0)
        {
            num+=temp%10;
            temp/=10;
        }
        a.insert(num);
    }
    cout << a.size() << endl;
    for(ita=a.begin(); ita!=a.end(); ita++)
    {
        if(flag!=0)
            cout << " ";
        cout << *ita;
        flag++;
    }
    return 0;
}

知识总结:
1.用set类型来存储值,一方面数字是按升序排列,另一方面在存储时是没有重复的插入

1065
解题思路:
1.设置一个couple数组来存放夫妻ID,下标为a中存放b;下标为b中存放a
2.设置guest来存放参加晚会的ID,如果参见晚会的人有对象,则在isExist数组中存放参见晚会的人的对象值为1
表示参加晚会的人的对象的对象来参加晚会了,如下图所示
3.要删除isExist中值为1的元素,保存值为0的元素
4.最后按要求输出

参考代码:

#include 
#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     int n, a, b, m;
     cin >> n;
     vector<int> couple(100000, -1);   //设置一个长度为100000,初值为-1的数组couple , 设置数组长度为100000是因为数组下标是00000~99999

     for (int i = 0; i < n; i++)   //将配对的数字,一个做下标,一个做元素值
     {
         scanf("%d%d", &a, &b);
         couple[a] = b;
         couple[b] = a;
     }

     cin >> m;
     vector<int> guest(m), isExist(100000);   //isExist也是数组长度为100000,因为下标也是从00000~99999

     for (int i = 0; i < m; i++)  //将所有输入的客人的配偶做下标,值设为1
     {
         cin >> guest[i];
         if (couple[guest[i]] != -1)
            isExist[couple[guest[i]]] = 1;
     }

     set<int> s;
     for (int i = 0; i < m; i++)    //主要删除此人及配偶
     {
         if (!isExist[guest[i]])
            s.insert(guest[i]);
     }
     printf("%d\n", s.size());
     for (auto it = s.begin(); it != s.end(); it++)
     {
         if (it != s.begin())
            printf(" ");
         printf("%05d", *it);
     }
     return 0;
}

解题思路2:
1.设置一个2列,n行的一个二维数组来存储夫妻对数
2.b来存放参加晚会的人
3.xunzhao函数表示如果此人有对象则返回其对象的下标,如果此人没对象则返回100000
4.循环b结合xunzhao函数,如果参加晚会的人有对象,继续在b中查找其对象是否存在,若存在则删除此人及其对象
5.最后按要求输出
6.可惜超时

参考代码:

#include
#include
using namespace std;
/*
    解题思路:

*/
int a[50001][2];
int n;
int xunzhao(int temp)  //对a而言,如果在二维数组中没有就返回0,如果有就返回其对应的值
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<2; j++)
        if(a[i][j]==temp)
            if(j==0)
                return a[i][1];
            else
                return a[i][0];
    }
    return 100000;
}
int main()
{
    cin >> n;
    for(int i=0; i<n; i++)
        for(int j=0; j<2; j++)
            cin >> a[i][j];
    set<int> b;
    set<int>::iterator itb;
    int m,flag=0;
    cin >> m;
    for(int i=0; i<m; i++)
    {
        int temp;
        cin >> temp;
        b.insert(temp);
    }
    //消除在此set中有配偶的
    for(itb=b.begin(); itb!=b.end(); itb++)
    {
        if(xunzhao(*itb)!=100000)
            if(b.find(xunzhao(*itb))!=b.end())
            {
                b.erase(xunzhao(*itb));
                b.erase(*itb);
            }
    }
    cout << b.size() << endl;
    for(itb=b.begin(); itb!=b.end(); itb++)
    {
        if(flag!=0)
            cout << " ";
        cout << *itb;
        flag++;
    }
    return 0;
}

1066
解题思路:
过于简单没有解题思路

参考代码1:

#include
using namespace std;
int main()
{
    int m,n,a,b,k;
    cin >> m >> n >> a >> b >> k;
    int l[n];
    for(int i=0; i<m; i++)
    {
        for(int j=0; j<n; j++)
            cin >> l[j];
        for(int j=0; j<n; j++)
        {
            if(j!=0)
                cout << " ";
            if(l[j]<a || l[j]>b)
                printf("%03d",l[j]);
            else
                printf("%03d",k);
        }
        cout << endl;
    }
    return 0;
}

参考代码2:

#include
using namespace std;
int main()
{
    int m,n,a,b,k,temp;
    cin >> m >> n >> a >> b >> k;
    for(int i=0; i<m; i++)
    {
        for(int j=0; j<n; j++)
        {
            scanf("%d",&temp);              //不用设置数组来存放,因为在循环中如果有一个输入,一个输出,如果一次性全部输入,那么对应的输出也是一次性全部输出,并非输入一个就显示一个。这里如果用cin输入就会超时
            if(temp>=a && temp<=b)
                temp=k;
            if(j!=0)
                cout << " ";
            printf("%03d",temp);
        }
        cout << endl;
    }
    return 0;
}

1067
解题思路1:
1.while设置为死循环
2.还是输入一个,输出一个,不是等到全部输入完后在输出
3.如果是正确的密码且尝试次数不超过 N,则在一行中输出 Welcome in,并结束程序;
如果是错误的,则在一行中按格式输出 Wrong password: 用户输入的错误密码;
当错误尝试达到 N 次时,再输出一行 Account locked,并结束程序
就按照这个策略去构建代码,不要自己胡推

参考代码:

#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     string password, temp;
     int n, cnt = 0;
     cin >> password >> n;
     getchar();
     while(1)
     {
         getline(cin, temp);
         if (temp == "#")
          break;
         cnt++;
         if (cnt <= n && temp == password)
         {
             cout << "Welcome in";
             break;
         }
         else if (cnt <= n && temp != password)
         {
             cout << "Wrong password: " << temp << endl;
             if (cnt == n)
             {
                 cout << "Account locked";
                 break;
             }
         }
     }
     return 0;
 }

注意事项:
1.在上面代码中不要忘记在第一次输入完后再输入getchar()接受缓冲区中的回车,以方便后面在循环中继续输入
2.此题的思路并非等所有输入完后在输出

解题思路2:
1.如果是正确的密码且尝试次数不超过 N,则在一行中输出 Welcome in,并结束程序
2.如果是错误的,则在一行中按格式输出 Wrong password: 用户输入的错误密码
3.当错误尝试达到 N 次时,再输出一行 Account locked,并结束程序。
4.用while开始输入,统计当前输入的个数,

参考代码:

#include
#include
#include
using namespace std;
/*
    解题思路:


*/
int main()
{
    string mima,temp="ds";
    int n,count=1;
    cin >> mima >> n;
    scanf("\n");
    vector<string> a;
    while(temp.compare("#")!=0)
    {
        getline(cin,temp);
        a.push_back(temp);
    }
    for(int i=0; i<a.size(); i++)
    {
        if(a[i].compare(mima)!=0 && count<=n)
        {
             printf("Wrong password: ");
             cout << a[i] << endl;
        }

        if(a[i].compare(mima)!=0 && count>n)
        {
             cout << "Account locked";
             return 0;
        }

        if(a[i].compare(mima)==0 && count>n)
        {
             cout << "Account locked";
             return 0;
        }

        if(a[i].compare(mima)==0)
        {
            cout << "Welcome in";
            return 0;
        }
        count++;
    }
    return 0;
}

1068
解题思路1:
1.第一行和第1列肯定都不要想,最后一行,一列的值也不要想
2.还是用二维数组去存储
3.用该值去见上下的,左右的,主队角线上的,副对角线上的差值必须大于tol才行

参考代码:

#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int m,n,tol,cnt=0,s,b;
    cin >> m >> n >> tol;
    int a[n][m];
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
            cin >> a[i][j];
    }
    for(int i=1; i<n-1; i++)
    {
        for(int j=1; j<m-1; j++)
        {
            if(a[i][j]-a[i][j-1]>tol && a[i][j]-a[i][j+1]>tol && a[i][j]-a[i-1][j]>tol && a[i][j]-a[i+1][j]>tol && a[i][j]-a[i-1][j-1]>tol && a[i][j]-a[i+1][j+1]>tol && a[i][j]-a[i-1][j+1]>tol && a[i][j]-a[i+1][j-1]>tol)
            {
                s=i;
                b=j;
                cnt++;
            }
        }
    }
    if(cnt==1)
        printf("(%d, %d): %d",b+1,s+1,a[s][b]);
    else if(cnt>1)
        cout << "Not Unique";
    else if(cnt==0)
        cout << "Not Exist";

    return 0;
}

解题思路2:
1.设置一个2维数组v,dir表示该点周围的8个点的位置(按照顺时针的顺序)
2.判断该点是否符合要求的函数judge
1.循环是8次
2.i,j分别表示行和列
3.tx,ty分别表示i,j周围的点的坐标
4.tx取值范围是0–n-1,ty取值范围是0–m-1,v[i][j]-v[tx][ty]<=tol或者v[i][j]-v[tx][ty]>=-tol,返回false
3.将2维数组设为n行m列的数组
4.按照行-列的顺序依次输入,并且mapp[i][j]++,表示该数字必须只有1个
5.用双层for循环统计符合要求的数字的个数cnt
6.最后根据cnt的值按要求输出

参考代码:

#include 
#include 
#include 
using namespace std;
/*
    解题思路:

*/
int m, n, tol;
vector<vector<int>> v;
int dir[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1},{0, -1}};

bool judge(int i, int j)
{
     for (int k = 0; k < 8; k++)
     {
         int tx = i + dir[k][0];    //行,下面代码中i是从0~n-1
         int ty = j + dir[k][1];   //列,下面代码中j是从0~m-1
         //tx,ty分别表示周围8个点的坐标,它的意思是直接判断这些坐标所代表的值是否符合要求,自动排除了,所有第1行(列),最后1行(列)的点
         if (tx >= 0 && tx < n && ty >= 0 && ty < m && v[i][j] - v[tx][ty] >= 0 - tol && v[i][j] - v[tx][ty] <= tol)
            return false;
     }
     return true;
 }

int main()
{
     int cnt = 0, x = 0, y = 0;
     cin >> m >> n >> tol;              //m是列,n是行
     v.resize(n, vector<int>(m));          //resize(),设置大小(size); 设置一个n行,每一行放一个长度为m的数组
     map<int, int> mapp;
     
     for (int i = 0; i < n; i++)
     {
         for (int j = 0; j < m; j++)
         {
             cin >> v[i][j];
             mapp[v[i][j]]++;   //这个mapp表示比如在输入样例1中 0有8个,65280有23个。。。
         }
     }
     
     
     for (int i = 0; i < n; i++)
     {
         for (int j = 0; j < m; j++)
         {
             if (mapp[v[i][j]] == 1 && judge(i, j) == true)
             {
                 cnt++;
                 x = i + 1;
                 y = j + 1;
             }
         }
     }
     

 }

注意事项:
1.其实并不是所有第1行(列),最后1行(列)的点不考虑,这些点只与剩下的3或者5个点比较
2.对于输入样例1,其实16711479和16711680都合适,为啥结果只有16711680,因为16711479满足条件的有2个

1069
解题思路:
1.先判断输入的字符串在之前是否存在,如果是就s=s+1(s表示要输出的位置)
2.当i==s时,并且这个位置的字符串之前没有
1.先mapp[str]设为1
2.输出
3.改变合适的位置s
4.设置一个flag初值为0,如果有中奖的则把flag改为1
3.当循环结束时,根据flag的值看是否输出Keep going…

参考代码;

#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     int m, n, s;
     cin >> m >> n >> s;
     string str;
     map<string, int> mapp;
     bool flag = false;
     for (int i = 1; i <= m; i++)
     {
         cin >> str;
         if (mapp[str] == 1)
            s+=1;
         if (i == s && mapp[str] == 0)  //按照规定的间隔输出,还要保证之前没有得过奖
         {
             mapp[str] = 1;
             cout << str << endl;
             flag = true;
             s+=n;
         }
     }
     if (flag == false)
        cout << "Keep going...";
     return 0;
 }

1070
解题思路:
1.将这个数字排序
2.从最小的两个开始就一路计算

参考代码:

/*
    解题思路:

*/
#include
#include
using namespace std;
int main()
{
    int n;
    cin >> n;
    int a[n];
    for(int i=0; i<n; i++)
        cin >> a[i];
    sort(a,&a[n]);             //默认为从小到大
    double sum=(double)(a[0]+a[1])/2;
    for(int i=2; i<n; i++)
    {
        sum=(sum+a[i])/2;
    }
    cout << (int)sum;
}

1072
解题思路:
1.根据输入的值,优先判断如果total=0则输出Game Over.并且退出循环,如果total 2.根据b的值和实际的n1和n2的大小来计算total的值

参考代码:

#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int T,k,n1,b,n2,total,t;
    cin >> T >> k;
    total=T;
    for(int i=0; i<k; i++)
    {
        cin >> n1 >> b >> t >> n2;
        if(total==0)
        {
            cout << "Game Over.";
            break;
        }
        else if(total < t)
            cout << "Not enough tokens.  " << "Total = " << total << "." << endl;
        else if((b==0 && n1>n2) || (b==1 && n1<n2))
        {
            total+=t;
            cout << "Win " << t << "!" << "  " << "Total = " << total << "."  << endl;
        }
        else if((b==0 && n1<n2) || (b==1 && n1>n2))
        {
            total-=t;
            cout << "Lose " << t << "." << "  " << "Total = " << total << "."  << endl;
        }
    }
    return 0;
}

1072
解题思路1;
1.用map来存储,名字作为关键字,后面跟着一个数组
2.输出一个值,就在set中找,找到就按格式输出,并统计人数和物品数

参考代码:

#include
#include
#include
#include
#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int n,m,count=0,count1=0;
    cin >> n >> m;
    set<int> s;
    map<string,vector<int>> a;
    for(int i=0; i<m; i++)
    {
        int temp;
        cin >> temp;
        s.insert(temp);
    }
    for(int i=0; i<n; i++)
    {
        string t;
        int p;
        cin >> t >> p;
        int flag=1,flag1=1;
        for(int j=0; j<p; j++)
        {
            int o;
            cin >> o;
            if(s.find(o)!=s.end())
            {
                if(flag==1)
                { 
                    cout << t << ": ";
                    count1++;
                }

                if(flag1==0)
                    cout << " ";
                printf("%04d", o);
                flag1=0;
                flag=0;
                count++;
            }
        }
        if(flag==0)
            cout << endl;
    }
    cout << count1 << " " << count;
}

解题思路2:
1.设置一个bool类型数组,以违禁品的编号为下标,数组元素为true
2.根据学生的物品对应于bool类型数组,按格式输出

参考代码:

#include
using namespace std;
bool kk[10000];
int main()
{
    int n,m,temp,a=0,b=0;
    cin >> n >> m;
    for(int i=0; i<m; i++)
    {
        cin >> temp;
        kk[temp]=true;
    }

    for(int i=0; i<n; i++)
    {
        string name;
        int k,flag=1;
        cin >> name >> k;
        for(int j=0; j<k; j++)
        {
            cin >> temp;
            if(kk[temp])
            {
                if(flag==1)
                    cout << name << ":";
                printf(" %04d",temp);
                a++;
                flag=0;
            }
        }
        if(flag==0)
        {
           cout << endl;
           b++;
        }
    }
    cout << b << " " << a;
}

1073
知识总结:

1073
1.解题思路:
一.第一个双层for循环
1.对于每道题的满分情况放到数组fullscore中,对于每道题选项个数放到optnum中,对于每道题正确选项个数放到
truenum中
2.根据truenum循环将每个学生每道题的按照hash的方式得到的分数放到trueopt数组中
二.第二个多层for循环:根据学生的答题情况,得出对应的分数,并输出;同时记录错的多的选项
三.找出cnt数组中的最大值maxcnt,表示错题数最大值
四.如果maxcnt为0输出too simple,否则双层for循环,找到与错题最大值相符的题目,同时输出错选的选项

2.参考代码:

#include 
#include 
#include 
using namespace std;
/*
    解题思路:


*/
int main()
{
     int n, m, optnum, truenum, temp, maxcnt = 0;
     int hash[] = {1, 2, 4, 8, 16}, opt[1010][110] = {0};   //opt数组表示每行是学生答题的分数情况
     char c;
     cin >> n >> m;
     vector<int> fullscore(m), trueopt(m);    //fullscore表示每道题满分的情况
     vector<vector<int>> cnt(m, vector<int>(5));  //表示一个二维数组,m行,每行表示一个长度为5的数组
                //cnt表示错误次数

      //输入前面一部分
     for (int i = 0; i < m; i++)
     {
         cin >> fullscore[i] >> optnum >> truenum;  //fullscore[i]表示满分数组
         for (int j = 0; j < truenum; j++)
         {
             scanf(" %c", &c);
             trueopt[i] += hash[c-'a'];   //trueopt[]数组统计一道题得满分时的分数
         }
     }

     for (int i = 0; i < n; i++)
     {
         double grade = 0;
         for (int j = 0; j < m; j++)
         {
             getchar();   //接受学生每道题答案之间的那个空格
             scanf("(%d", &temp);

             for (int k = 0; k < temp; k++)
             {
                 scanf(" %c)", &c);            //先把学生的答案输入进去
                 opt[i][j] += hash[c-'a'];   //计算opt对应的值
             }

             /*
                1.通过异或运算找出全对和 选错或者漏选
                2.用过按位或找出漏选
                3.记录错误的个数(通过按位与)
             */
             int el = opt[i][j] ^ trueopt[j];    //^ 不同是非0,相同为0  el就是判断答案是否相同

             if (el)        //表示el不为0,就数值不同,一种半对半错,一种是全错
             {
                 if ((opt[i][j] | trueopt[j]) == trueopt[j])  //与0计算结果是原值,与1计算结果是1
                 { //这种情况计算的是半对半错
                    grade += fullscore[j] * 1.0 / 2;
                 }

                 if (el)   //这种情况计算的是全错,el是非0,此时要记录错误的选项
                 {
                     for (int k = 0; k < 5; k++)   //一共最多有5个答案,分别是abcde
                        if (el & hash[k])         //与0计算结果为0,与1运算结果为原值,按位与,只有对应的两个二进位都为1时,结果位才为1,参与运算的两个数均以补码出现
                            cnt[j][k]++;
                 }
             }
             else     //表示el为0,就数值相同就grade直接加
             {
                grade += fullscore[j];
             }
         }
         printf("%.1f\n", grade);
     }

     //找出错的最多的题目的错误个数
     for (int i = 0; i < m; i++)
        for (int j = 0; j < 5; j++)
            maxcnt = maxcnt > cnt[i][j] ? maxcnt : cnt[i][j];

    //如果这个maxcnt为0,表示没有题目让学生答错
     if (maxcnt == 0)
     {
        printf("Too simple\n");
     }
     else
     {
         for (int i = 0; i < m; i++)
         {
             for (int j = 0; j < 5; j++)
             {
                 if (maxcnt == cnt[i][j])       //
                    printf("%d %d-%c\n", maxcnt, i+1, 'a'+j);
             }
         }
     }
     return 0;
 }

知识总结:
1.对于本题中判断学生的答案与标答是否一致用:

/*
	用异或语句,如果答案与标答一致则el为0,否则el为非0
*/
int el = opt[i][j] ^ trueopt[j];

2.对于本题中判断学生的答案是否为半对半错用:

/*
	用按位与计算,如果是半对半错则下面执行if下的语句,否则不执行
*/
if ((opt[i][j] | trueopt[j]) == trueopt[j])

3.对于本题中判断学生的答案是否全错用:

if (el)

如果答案为全错,还要记录错误答案是哪个用:

                     for (int k = 0; k < 5; k++)   //一共最多有5个答案,分别是abcde
                        if (el & hash[k])         //与0计算结果为0,与1运算结果为原值,按位与,只有对应的两个二进位都为1时,结果位才为1,参与运算的两个数均以补码出现
                            cnt[j][k]++;

其中cnt结果如下图
pat乙级1001,1002_第15张图片
根据循环得到cnt的过程如下:
pat乙级1001,1002_第16张图片

对于上图中的解释如下:

第一题:对于CNT的理解。是这么理解的。对于你看,对于第一题正确答案是ac,根据三个学生的答案。第三名学生,他的答案是个BD。正确答案是ac,意思就是说。打错了,是BD,你没答是ac。这是第一题

第二题:对于第二题。正确答案是B。第一个学生答错d e。第二个学生,答案正确,第三个学生。打错e

第三题:对于第三题,正确答案是BC。第一个学生答,错是a,没达世币。第二个学生,第二个学生。他。打错了,是a,没达是C。对于第三个学生。打错是B

第四题:对于第四题,正确答案是abde第一个学生。没打底。第二个答案正确,第三个学生。答错,是c没答是e

4.opt数组结果如下:

pat乙级1001,1002_第17张图片

5.对于trueopt数组如下:
pat乙级1001,1002_第18张图片

6.对于hash数组如下:
pat乙级1001,1002_第19张图片

7.scanf在for中的一些输入

#include 
#include 
#include 
using namespace std;
int main()
{

int temp;
char c;
             scanf("(%d", &temp);
             for (int k = 0; k < temp; k++)
             {
                 scanf(" %c)", &c);
                cout << c << " ";
             }

     return 0;
 }

pat乙级1001,1002_第20张图片
pat乙级1001,1002_第21张图片

1074
解题思路:
1.将两个要相加的pat数,左边补充其位置使其和第一个字符串长度一致
2.for循环,从最后一位开始,先判断如果是10进制,则mod为10;否则就为对应的值
3.求余数,将其放到ans的最后一位;求其进位的数carry
4.如果进位的数carry不为0,一律设置为1,在最左边补为1
5.for循环输出,如果全为0,和第一个位置值为0,则都不输出

参考代码:

#include
using namespace std;
/*
    知识总结:
    1.设置为指定长度,指定值的字符串(长度为s-s1的长度,初值全设置为0)
        string ss1(s.length()-s1.length(),'0');
*/
int main()
{
    string s,s1,s2,ans;
    int carry=0,flag=0;
    cin >> s >> s1 >> s2;
    string ss1(s.length()-s1.length(),'0');
    s1=ss1+s1;
    string ss2(s.length()-s2.length(),'0');
    s2=ss2+s2;
    ans=s;

    for(int i=s.length()-1; i>=0; i--)
    {
        int mod=s[i]=='0'?10:(s[i]-'0');
        ans[i]=(s1[i]-'0'+s2[i]-'0'+carry)%mod+'0';
        carry=(s1[i]-'0'+s2[i]-'0'+carry)/mod;
    }
    if(carry!=0)
        ans='1'+ans;
    for(int i=0; i<ans.length(); i++)
    {
        if(ans[i]!='0' || flag==1)
        {
            flag=1;
            cout << ans[i];
        }
    }
    if(flag==0)
        cout << 0;
    return 0;
}

知识总结:
1.设置为指定长度,指定值的字符串(长度为s-s1的长度,初值全设置为0)

        string ss1(s.length()-s1.length(),'0');

1075
解题思路:
1.设置一个结构数组里面存放data和下标,设置3个vector线性表的数组
2.用地址作为下标,输入data,在输入next
3.从start开始,一直循环,根据data将<0和<=k和其他数字,分别将其地址放到v[0],v[1],v[2]
4.最后按照vector输出,也是双层for循环,按要求输出v[i][j],list[v[i][j]]…

参考代码:

#include 
#include 
/*
    解题思路:

*/

using namespace std;
struct node 
{
    int data, next; 
}list[100000];

vector<int> v[3];  //3个vector线性表

int main() 
{
        int start, n, k, a;
     cin >> start >> n >> k;
     for (int i = 0; i < n; i++) 
     {
         cin >> a;
         cin >> list[a].data >> list[a].next;
     }
     
     int p = start;
     
     while(p != -1) 
     {
         int data = list[p].data;
         if (data < 0)
            v[0].push_back(p);        //v[0]全部存放<0
         else if 
            (data >= 0 && data <= k)
         v[1].push_back(p);         //v[1]全部存放<=k
         else
            v[2].push_back(p);
         p = list[p].next;
     }
     
     int flag = 0;
     for (int i = 0; i < 3; i++) 
     {
         for (int j = 0; j < v[i].size(); j++) 
         {
             if (flag == 0) 
             { //设置flag的作用是因为在排列后最后一个位置下标为-1,所以整个输出时先设置flag输出下标,空格,data,空格
                 printf("%05d %d ", v[i][j], list[v[i][j]].data);
                 flag = 1;
             } 
             else 
             {
                printf("%05d\n%05d %d ", v[i][j], v[i][j], list[v[i][j]].data);
             }
         }
     }
     printf("-1");  //最后再输出-1
     return 0; 
 }

知识总结:
1.设置一个3个线性表的vector数组:

vector<int> v[3];

2.设置结构数组:

struct stu
{
    int data,next;
}list[100001];

1076
参考代码1:

#include
using namespace std;
/*
    解题思路:
    
*/
int main()
{
    int n;
    cin >> n;
    int a[]={1,2,3,4};
    string temp,num;
    for(int i=0; i<n; i++)
        for(int j=0; j<4; j++)
        {
            cin >> temp;
            if(temp[2]=='T')
                 num+=a[temp[0]-'A']+'0';
        }
    cout << num;
    return 0;
}

参考代码2:

#include
using namespace std;
int main()
{
    string s;
    while(cin >> s)
    {
        if(s.size()==3 && s[2]=='T')
            cout << s[0]-'A'+1;
    }
    return 0;
}

1077
解题思路:
1.输入n,m
2.双层for循环,外层输入老师给的成绩g2,内存for循环:1.找出最大,最小值,2.并且统计所有符合条件的值,3.统计
满足条件的人数
3.按照格式输出对应的成绩

参考代码:

#include 
using namespace std;
/*

*/
int main()
{
     int n, m;
     cin >> n >> m;
     for (int i = 0; i < n; i++) 
     {
         int g2, g1 = 0, cnt = -2, temp, maxn = -1, minn = m + 1;
         cin >> g2;
         for (int j = 0; j < n-1; j++) 
         {
             cin >> temp;
             if (temp >= 0 && temp <= m) 
             {
                 if (temp > maxn) 
                    maxn = temp;
                 if (temp < minn) 
                    minn = temp;
                 g1 += temp;
                 cnt++;
             }
         }
         cout << int((((g1 - minn - maxn) * 1.0 / cnt) + g2) / 2 + 0.5) << endl;
     }
     return 0; 
 }

注意事项:

cnt的值一定要设置为cnt-2因为在cnt++中包括了最大,最小值

1078
解题思路:
1.使用if-else语句,分别构建压缩和解压的代码
2.对于解压:
1.for循环嵌套if-else
1.for循环是根据字符串的长度
2.if-else是根据判断s[i]是否在’1’~'9’之内
3.是的话,就num+=s[i]
4.不是的话,就根据num的长度将其转化为数字,循环输出对应的字符
5.切记将cnt改为1(保证出现单个字符串时能够输出),同时将num改为""
6.为什么要用string类型的num,因为输入的字符串是string类型的,所以可以方便的接受
7.为什么要加 if (num.length() > 0)这个判断,因为当num的长度为0,是无法转化成数字,程序界面提示
会超出范围,这也就是为啥后面设置cnt为1以便能够让单个字符也能输出
3.对于压缩
1.对于每一小串相同字符的字符串,每次取出第一个字符,然后统计其个数,再循环输出
2.切记,当for按照字符串的长度循环结束时,最后还要输出剩余字符串

参考代码:

#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     char t;
     cin >> t;
     getchar();        //接受上面的回车
     string s, num;
     getline(cin, s);
     int cnt = 1;
     if (t == 'D') //解压
     {
         for (int i = 0; i < s.length(); i++)
         {
             if (s[i] >= '0' && s[i] <= '9')
             {
                num += s[i];
             }
             else
             {
                 if (num.length() > 0)
                    cnt = stoi(num);     //将字符串转化为数字
                 while(cnt--)
                    cout << s[i];
                 cnt = 1;               //cnt设置为1,是因为要保证必须有一个字符输出
                 num = "";
             }
         }
     }
     else            //压缩
     {
         char pre = s[0];
         for (int i = 1; i < s.length(); i++)
         {
             if (s[i] == pre)
             {
                cnt++;
             }
             else
             {
                 if (cnt >= 2)
                    cout << cnt;
                 cout << pre;
                 cnt = 1;
                 pre = s[i];         //s[i]此时表示第1个值
             }
         }
         if (cnt >= 2)           //当整个字符串结束后,输出剩余的值
            cout << cnt;
         cout << pre;
     }
     return 0;
 }

知识总结:
1.将字符串转化为数字

string s="9";
int a=stoi(s);
cout << a; //此时a的值即为9

1079
解题思路1:
1.用while循环,当出现回文数时或者执行步骤>=10,就退出循环
2.输出字符串和其扭转的字符串,再输出两个字符串相加的值
3.再将两个数字相加的值转化为字符串
4.统计每次计算的步骤

参考代码:

#include
#include
#include
#include
using namespace std;
/*
    解题思路:

*/
bool panduan(string s)
{
    for(int i=0; i<s.length(); i++)
        if(s[i]!=s[s.length()-i-1])
            return 0;
    return 1;
}
string fuhui(int a)
{
    string s;
    stringstream ss;
    ss << a;
    ss >> s;
    return s;
}
int main()
{
    string s,s1="12",s2;
    int num=0;
    cin >> s;
    if(panduan(s))       //如果输入的字符串本身就是回文,就直接输出,不要相加
    {
        cout << s << " is a palindromic number.";
        return 0;
    }

    while(!panduan(s1) && num<10)
    {
        s2=s;
        reverse(s.begin(),s.end());
        cout << s2 << " + " << s << " = " << stoi(s2)+stoi(s) << endl;
        s1=fuhui(stoi(s2)+stoi(s));
        s=s1;
        num++;
    }
    if(num==10)
        cout << "Not found in 10 iterations.";
    else
        cout << s1 << " is a palindromic number.";

}


知识总结:
1.将数字转化为字符串

#include
#include
#include
using namespace std;
int main()
{
    int a=3333;
    string s;
    stringstream ss;
    ss << a;
    ss >> s;
    cout << s;


}

2.扭转一个字符串

//扭转一个STL字符串
#include 
#include 
#include 
	using namespace std;
int main()
{


	string strSample;
	cin >> strSample;
	cout << strSample << endl << endl;

	reverse(strSample.begin(), strSample.end());
	cout << strSample;

	return 0;
}

解题思路2:
1.将字符串扭转的函数rev,模拟手动相加字符串的函数add
2.首先判断输入的字符串是否为回文是就输出,否则不管
3.while,循环条件是n–,n=10
1.对于字符串和其自身的扭转先相加
2.按照题意输出
3.if判断,如果是回文就输出,并且结束程序
4.当循环结束时,只能输出Not found in 10 iterations.

4.add函数
     1.s1表示原始字符串,s2表示其扭转的字符串
     2.设置一个变量carry表示进的那一位
     3.根据原始字符串长度,从最后一个位置开始模拟相加

参考代码:

#include 
#include 
using namespace std;
/*
    解题思路:

    
*/
string rev(string s)     //rev表示将字符串扭转
{
     reverse(s.begin(), s.end());
     return s;
}
string add(string s1, string s2)  //手动模拟字符串的相加
{
     string s = s1;
     int carry = 0;         //carry表示进的那一位
     for (int i = s1.size() - 1; i >= 0; i--)
     {
         s[i] = (s1[i] - '0' + s2[i] - '0' + carry) % 10 + '0';
         carry = (s1[i] - '0' + s2[i] - '0' + carry) / 10;
     }
     if (carry > 0)   //一定是先给s1前加1,在返回,否则直接return "1"+s就报错
        s = "1" + s;
     return s;
 }
int main()
{
     string s, sum;
     int n = 10;
     cin >> s;
     if (s == rev(s))
     {
                cout << s << " is a palindromic number.\n";
         return 0;
     }
     while (n--)
     {
         sum = add(s, rev(s));    //计算字符串和其扭转的字符串相加
         cout << s << " + " << rev(s) << " = " << sum << endl;
         if (sum == rev(sum))
         {
             cout << sum << " is a palindromic number.\n";
             return 0;
         }
         s = sum;
     }
     cout << "Not found in 10 iterations.\n";
     return 0;
 }

1080
解题思路:
1.设置结构node,其中结构成员包括人名,鸡屎成绩,其中成绩,期末成绩,总成绩
2.用vector设置结构数组,这样可以设置cmp,来按照总成绩降序排列,人名升序排列
3.设置一个map类型变量idx,他的作用从参加其中,期末考试的人中找到参加鸡屎的人
4.如果最终成绩>=60,就将其放到结构数组ans中
5.对ans进行cmp排列,最后输出即可

参考代码:

#include 
#include 
#include 
#include 
/*
    解题思路:

*/
using namespace std;
struct node           //定义一个结构,
{
 string name;
 int gp, gm, gf, g;
};

bool cmp(node a, node b)  //设置一个按照最终成绩的递减排列,按照名字的递增排列
{
 return a.g != b.g ? a.g > b.g : a.name < b.name;
}

map<string, int> idx;

int main()
{
     int p, m, n, score, cnt = 1;
     cin >> p >> m >> n;
     vector<node> v, ans;   //设置一个结构数组
     string s;
     for (int i = 0; i < p; i++)
     {
         cin >> s >> score;
         if (score >= 200)   //当成绩>200时,直接将node结构放到数组中,并且对成绩大于200的这些人从1开始编号
         {
             v.push_back(node{s, score, -1, -1, 0});
             idx[s] = cnt++;
         }
     }
     for (int i = 0; i < m; i++)
     {
         cin >> s >> score;
         if (idx[s] != 0)     //要找出即参加机示的人且参加其中考试的人
            v[idx[s] - 1].gm = score;   //将期中成绩对应的放到结构中
     }
     for (int i = 0; i < n; i++)
     {
         cin >> s >> score;
         if (idx[s] != 0)               //要找出即参加机示的人且参加期末考试的人
         {
             int temp = idx[s] - 1;
             v[temp].gf = v[temp].g = score;  //先把所有的期末成绩gf和最终成绩g都先设置为期末考试成绩
             if (v[temp].gm > v[temp].gf)   //如果其中考试成绩gm>gf则按要求计算g
                v[temp].g = int(v[temp].gm * 0.4 + v[temp].gf * 0.6 + 0.5);
         }
     }

     for (int i = 0; i < v.size(); i++)
        if (v[i].g >= 60)
            ans.push_back(v[i]);
     sort(ans.begin(), ans.end(), cmp);
     for (int i = 0; i < ans.size(); i++)
        printf("%s %d %d %d %d\n", ans[i].name.c_str(), ans[i].gp, ans[i].gm,ans[i].gf, ans[i].g);
     return 0;
 }

注意事项:
1.如果将cnt设为0,后面代码中:
if(idx[s]!=0) 改为 if(idx[s]>=0)
v[idx[s]-1].gm=score; 改为 v[idx[s]].gm=score;
int temp=idx[s]-1; 改为 int temp=idx[s];
但是如果在第一次for循环输入时,鸡屎没有>=200,那最后再输入下次循环的第一个值,就直接退出了,如下图所示
pat乙级1001,1002_第22张图片
正常代码的结果如下:就是没任何输入
pat乙级1001,1002_第23张图片

1081
解题思路:
1.for循环先输入字符串,然后if-else判断如果字符串长度>=6,则进入下一步;否则就输出字符串太短了
2.设置3个int类型且初值为0的三个变量int invalid = 0, hasAlpha = 0, hasNum = 0;
3.if-else if-else if构建:
1.如果字符不是小数点也不是字母和数字,设置invalid为1,最后根据invalid的值为1,来输出太乱了
2.进入第一个else if,如果字符是字母,则设置hasAlpha为1,最后根据hasAlpha的值为0,来输出缺少字母
3.进入第二个else if,如果字符是数字,则设置hasNum为1,最后根据hasNum的值为0,来输出缺少数字
4.如果没有以上情况,就输出完美

参考代码:

#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     int n;
     cin >> n;
     getchar();   //接受缓冲区的回车,
     for (int i = 0; i < n; i++)
     {
         string s;
         getline(cin, s);
         if (s.length() >= 6)
         {
             int invalid = 0, hasAlpha = 0, hasNum = 0;
             for (int j = 0; j < s.length(); j++)
             {
                 if (s[j] != '.' && !isalnum(s[j]))
                    invalid = 1;
                 else if
                    (isalpha(s[j]))
                        hasAlpha = 1;
                 else if (isdigit(s[j]))
                    hasNum = 1;
             }
             if (invalid == 1)
                cout << "Your password is tai luan le.\n";
             else if (hasNum == 0)
                cout << "Your password needs shu zi.\n";
             else if (hasAlpha == 0)
                cout << "Your password needs zi mu.\n";
             else
                cout << "Your password is wan mei.\n";
         }
        else
            cout << "Your password is tai duan le.\n";
     }
     return 0;
 }

知识总结:
1.如果用cin输入数字,紧接用getline输入,必须在二者之间加入getchar(),否则就在输入完数字后程序结束

#include 
#include 
using namespace std;

int main()
{
     int n;
     cin >> n;
     //getchar();    //
     string s;
     getline(cin,s);

     return 0;
 }

2.isalnum)用来判断字符是数字或者字母?是,返回true;否则,返回false
3.isalpha()用来判断字符是纯字母?是,返回true;否则,返回false
4.isdigit()用来判断字符是数字?是,返回true;否则,返回false

1082
解题思路1:
1.先计算两个数字的平方和dis
2.找出最大数字所对应的运动员编号
3.找出最小数字所对应的运动员编号
4.每次更新最大,最小值
5.输出

参考代码:

#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     int n, id, x, y, maxid, maxdis = -1, minid, mindis = 99999;
     cin >> n;
     for (int i = 0; i < n; i++)
     {
         cin >> id >> x >> y;
         int dis = x * x + y * y;
         if (dis > maxdis)
            maxid = id;
         if (dis < mindis)
            minid = id;
         maxdis = max(maxdis, dis);   
         mindis = min(mindis, dis);
     }
     printf("%04d %04d", minid, maxid);
     return 0;
 }

知识总结:
1.max函数,min函数

#include 
using namespace std;
int main()
{

    int a=5,b=3;
     cout << min(a,b);  //输出a,b中较小的值
     cout << max(a,b);   //输出a,b中较大的值

     return 0;
 }

解题思路2:

1.设置一个结构数组,并输入
2.通过循环找出求两个数字平方和的最大值下标和最小值下标
3.最后根据下标输出编号

参考代码:

#include
using namespace std;
/*
    解题思路:

*/
struct su
{
    int a,b,c;
};
int main()
{
    int n,max=0,min=0,max1=-1,min1=100003;
    cin >> n;
    su a[n];
    for(int i=0; i<n; i++)
        cin >> a[i].a >> a[i].b >> a[i].c;
    for(int i=1; i<n; i++)
    {
        if(a[i].b*a[i].b+a[i].c*a[i].c > a[max].b*a[max].b+a[max].c*a[max].c)
            max=i;
        if(a[i].b*a[i].b+a[i].c*a[i].c < a[min].b*a[min].b+a[min].c*a[min].c)
            min=i;
    }
   printf("%04d %04d",a[min].a,a[max].a);
}

1083
解题思路1:
1.设置一个长度为10000的数组a
2.将其计算结果作为数组下标,元素值++
3.从后向前输出,如果元素值>=2,则输出对应的下标也就是之前算的差值,并且再输出其元素值

参考代码:

#include 
using namespace std;
/*
    解题思路:

*/
int main() 
{
     int n, t, a[10000] = {0};
     cin >> n;
     for (int i = 1; i <= n; i++) 
     {
         cin >> t;
         a[abs(t-i)]++;
     }
     for (int i = 9999; i >= 0; i--)
        if (a[i] >= 2) 
            cout << i << " " << a[i] << endl;
     return 0; 
 }

解题思路2:
1.定义一个vector数组,然后计算与下标相减再减1,
2.对vector数组进行降序排列
3.循环输出重复出现>=2次的数,及其重复次数。(思想就是:每次取出第一个,然后与后面的值比较统计其重复次数)

参考代码:

#include
#include
#include
#include
/*
    

*/
using namespace std;
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int n;
    cin >> n;
    vector<int>a(n);
    for(int i=0; i<n; i++)
    {
        cin >> a[i];
        a[i]=abs(a[i]-i-1);
    }
    sort(a.begin(),a.end(),cmp);
    int temp=a[0],cnt=1;
    for(int i=1; i<n; i++)
    {
        if(temp==a[i])
            cnt++;
        else
        {
            if(cnt>=2)
                cout << temp << " " << cnt << endl;
            temp=a[i];
            cnt=1;
        }
    }
    if(cnt>=2)
        cout << temp << " " << cnt << endl;
    return 0;
}

1084
解题思路1:
1.zhuanhua()函数是将数字转化为字符串
2.xinzhi()函数是每次返回统计后的字符串(就像前面说的一样,统计重复出现的字符串个数)
3.main走一个循环即可

参考代码:

#include
#include
#include
using namespace std;
/*
    解题思路;
    1.用字符串s来报存,改变s,
*/
string zhuanhua(int a)
{
    string s;
    stringstream ss;
    ss << a;
    ss >> s;
    return s;
}
string xinzhi(string s)
{
    string num,s1;
    num+=s[0];
    int cnt=1;
    for(int i=1; i<s.length(); i++)
    {
        if(num[0]==s[i])
            cnt++;
        else
        {
            s1=s1+num+zhuanhua(cnt);
            num="";
            num+=s[i];
            cnt=1;
        }
    }
    s1=s1+num+zhuanhua(cnt);
    return s1;
}
int main()
{
    string s;
    int a;
    cin >> s >> a;
    for(int i=1; i<a; i++)
    {
        xinzhi(s);
        s=xinzhi(s);
    }
    cout << s;
}

解题思路2:
1.三层for循环,外层for是第n个;第2层for和第3层的作用就是比如:前面一个值是1121 通过此5行代码 就变成 122111
2.第二层for与第三层for:
1.以字符串的长度循环,但是循环的增量是i=j也就是下一小段相同字符串的第一个字符的位置
2.第3层for,j=i从这个位置开始,如果后面的字符和前面的相同,则j++统计相同字符的个数
3.最后将字符和相同字符的个数加到临时字符串变量t中

参考代码:

#include 
using namespace std;
int main()
{
     string s;
     int n, j;
     cin >> s >> n;
     for (int cnt = 1; cnt < n; cnt++)   //控制它的循环次数
     {
         string t;        //临时变量t
         for (int i = 0; i < s.length(); i = j)   //此行代码开始向下5行的作用就是
         {
             for (j = i; j < s.length() && s[j] == s[i]; j++)
                     ;  //统计相同字符的个数
                t += s[i] + to_string(j - i);   //+的优先级> +=  t表示前一个字符的结果,s[i]当前每一小段字符,to_string(j-i)实质表示相同字符的个数
         }
         s = t;
     }
     cout << s;
     return 0;
 }

知识总结:
1.将数字转化为字符串

to_string(123); //表示将数字123转化为字符串123

注意事项:
1.切记第3层for的循环语句是 ; 这个循环的目的是统计相同字符的个数
2.由于第2层的循环增量是i=j,所以要提前定义变量j,并且在第3层for的循环中,不能再定义临时变量j

1085
解题思路:
1.设置一个结构node,cmp排序
2.设置两个map类型
3.for循环输入信息
1.根据学校,将其字符串所有字符改为小写
2.每次根据题型算出对应的分数
3.以学校名为关键字,sum中成绩累加,cnt中人数累加
4.设置一个数组结构,将sum和cnt中的信息导入进数组结构,并且对数组结构进行cmp
5.按照要求输出

参考代码:

#include 
#include 
#include 
#include 
/*
    解题思路:

*/
using namespace std;
struct node
{
 string school;
 int tws, ns;     //tws就是总分,ns就是人数
};

bool cmp(node a, node b)
{
 if (a.tws != b.tws)    //如果总分不同,按照总分的降序排列
 return a.tws > b.tws;
 else if (a.ns != b.ns)  //如果总分相同,按照人数的升序排列
 return a.ns < b.ns;
    else
 return a.school < b.school;  //如果总分,人数相同,按照学校名的升序排列
 }

int main()
{
     int n;
     cin >> n;
     map<string, int> cnt;
     map<string, double> sum;
     for (int i = 0; i < n; i++)
     {
         string id, school;
         cin >> id;
         double score;
         cin >> score;
         cin >> school;

         for (int j = 0; j < school.length(); j++)
            school[j] = tolower(school[j]);

         if (id[0] == 'B')
            score = score / 1.5;
         else if (id[0] == 'T')
            score = score * 1.5;
         sum[school] += score;  //计算不同学校对应的总分
         cnt[school]++;       //统计人数
     }

     vector<node> ans;  //将信息放到ans数组结构中
     for (auto it = sum.begin(); it != sum.end(); it++)  //设置迭代器,将对应的信息放到ans中
        ans.push_back(node{it->first, (int)sum[it->first], cnt[it->first]});

     sort(ans.begin(), ans.end(), cmp);  //按照要求排序


     int rank = 0, pres = -1;
     cout << ans.size() << endl;

     for (int i = 0; i < ans.size(); i++)  //如果成绩不同,则按照i+1输出; 否则不变其排名
     {
         if (pres != ans[i].tws)
            rank = i + 1;
         pres = ans[i].tws;
         printf("%d ", rank);

         cout << ans[i].school;
         printf(" %d %d\n", ans[i].tws, ans[i].ns);
     }
     return 0;
 }

知识总结:
1.将字符串中的每个字符改为小写

#include
using namespace std;
int main()
{
    string s;
    cin >> s;
    for(int i=0; i<s.leng(); i++)
        s[i]=tolower(s[i]);
}

2.如果对vector中的三个信息需要比较的话,应该用if-else去设置

bool cmp(node a, node b)
{
 if (a.tws != b.tws)    //如果总分不同,按照总分的降序排列
 return a.tws > b.tws;
 else if (a.ns != b.ns)  //如果总分相同,按照人数的升序排列
 return a.ns < b.ns;
    else
 return a.school < b.school;  //如果总分,人数相同,按照学校名的升序排列
 }

1086
参考代码1

#include
#include
using namespace std;

int main()
{
    int a,b;
    cin >> a >> b;
    string s;
    stringstream ss;
    ss << a*b;
    ss >> s;
    for(int i=s.length()-1; i>=0; i--)
        cout << s[i];
}

参考代码2:

#include
#include
using namespace std;
int main()
{
    int a,b;
    cin >> a >> b;
    string s;
    s=to_string(a*b);
    reverse(s.begin(),s.end());
    cout << stoi(s);
}

知识总结:
1.将数字转换为字符串

    s=to_string(a*b);

2.扭转字符串

    reverse(s.begin(),s.end());

3.将数字字符串转化为数字

cout << stoi(s);

注意事项;
1.要注意最后将字符串一定转化为数字,否则有的测试点过不去

1087
参考代码:

#include
#include
using namespace std;
int main()
{
    int n;
    cin >> n;
    set<int> s;
    for(int i=1; i<=n; i++)
        s.insert(i/2+i/3+i/5);
    cout << s.size();
    return 0;
}

1088
解题思路:
1.将甲的值从99~1开始递减循环
2.先算出jia,yi,bing三个值,然后进行判断一但有满足条件的就退出
3.后面按照题意输出

参考代码:

#include
#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int x,y,my;
    cin >> my >> x >> y;
    int jia=0,yi,bing;
    for(jia=99; jia>=1; jia--)
    {
        yi=jia%10*10+jia/10;
        if(abs(jia-yi)%x==0)
            bing=abs(jia-yi)/x;
        if(bing!=0 && yi==bing*y)
        {
            break;
        }
    }
    if(jia==0)
    {
        cout << "No Solution";
        return 0;
    }
    else
    {
        string s=jia>my?"Cong":jia==my?"Ping":"Gai";
        string s1=yi>my?"Cong":yi==my?"Ping":"Gai";
        string s2=bing>my?"Cong":bing==my?"Ping":"Gai";
        cout << jia << " " << s << " " << s1 << " " << s2;
return 0;
    }

    return 0;
}

解题思路2:
1.输出m,x,y三个值
2.还是jia的值从99~10递减循环
3.计算出yi的值
4.切记将bing的值设为double类型
5.判断是否满足条件,满足就输出,然后return 0
6.最后再输出"No Solution"

参考代码2:

#include
#include
using namespace std;
int jia,yi,my;
double bing;
void print(double m)  //这个m由于还有bing的值,所以设置为double类型
{
    if(m==my)
        cout << " Ping";
    else if(m>my)
        cout << " Cong";
    else
        cout << " Gai";
}
int main()
{
    int x,y;
    cin >> my >> x >> y;
    for(jia=99; jia>=10; jia--)
    {
        yi=jia%10*10+jia/10;
        bing=abs(jia-yi)*1.0/x;
        if(yi==bing*y)
        {
            cout << jia;
            print(jia);
            print(yi);
            print(bing);
            return 0;
        }
    }
    cout << "No Solution";
    return 0;
}

1089
解题思路:
1.使用v数组来存放实时情况
2.3层for循环嵌套:
1.前2层循环是假设i,j=i+1是狼人,这样来最后判断出谁是狼人
2.在第2层for循环中要设置vector类型的数组lie,a分别表示说谎人的编号和人员成分的数组(意思是如下图所示)
3.第3层for循环用来判断2个说谎人的编号,将其放到lie数组中
4.如果lie的长度是2表示有2个说谎的人,并且说谎人的编号在数组a中对应的值相加为0,因为一个说谎的是狼人,那另一个说谎的好人,所以相加为0
5.至于有多个值,按照最小序列输出;本来就是i从1开始,并且j=i+1一直的证到n(也是从小到大)

pat乙级1001,1002_第24张图片

参考代码:

#include 
#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     int n;
     cin >> n;
     vector<int> v(n+1);

     for (int i = 1; i <= n; i++)
        cin >> v[i];     //v数组表示的是实时情况

     for (int i = 1; i <= n; i++)
     {
         for (int j = i + 1; j <= n; j++)
         { //a数组表示的就对应的编号是狼人,还是好人
             vector<int> lie, a(n + 1, 1);   //a是一个长度为n+1,并且初始值全为1的数组
             a[i] = a[j] = -1;  //1表示好人;-1表示狼人
             for (int k = 1; k <= n; k++)   //k从1~n分别判断k所说的是真是假
                if (v[k] * a[abs(v[k])] < 0) //k说的话和真实情况不同(v[k] * a[abs(v[k])] < 0)则表示k在说谎,将k放在lie数组中
                    lie.push_back(k);   // lie数组表示将说谎人的编号
             if (lie.size() == 2 && a[lie[0]] + a[lie[1]] == 0)  //如果说谎人数等于2并且这两个说谎的人一个是好人一个是狼人
            {//a[lie[0]] + a[lie[1]] == 0表示的意思是两个狼人中一个说谎一个说真话
                 cout << i << " " << j;
                 return 0;
            }
         }
     }
     cout << "No Solution";
     return 0;
}

1090
解题思路:
1.设置一个map类型的vector的数组,每次输入两个值,其中一个为关键字,另一个为元素值,在反过来设置下
2.根据k循环
1.cnt表示运输货物的个数,flag就是一个标签,a是以货物编号为下标,元素值初始都为0,但是将要运输的货物的
元素值设为1
2.双层for循环:
1.第一层以要运输的货物个数为准
2.第2层for是以与每个运输货物不相容的货物个数为下标,然后判断a[m[v[i]][j]]是否为1,为1表示运输的货物中有不相容的
最后按要求输出

参考代码:

#include 
#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main() 
{
     int n, k, t1, t2;
     map<int,vector<int>> m;
     scanf("%d%d", &n, &k);
     for (int i = 0; i < n; i++)   //设置一个关键字是int类型的值,它下面是一个vector的数组
     {
         scanf("%d%d", &t1, &t2);
         m[t1].push_back(t2);
         m[t2].push_back(t1);
     }
     while (k--) 
     {
         int cnt, flag = 0, a[100000] = {0};  //0表示不相容
         scanf("%d", &cnt);
         vector<int> v(cnt);
         for (int i = 0; i < cnt; i++) 
         {
             scanf("%d", &v[i]);     //v[i]是运输货物的编号
             a[v[i]] = 1;          //此行代码的意思是将所有要运输的货物下标设为1,其余都是0
         }
     
         for(int i=0; i<v.size(); i++)     //第一层for遍历循环每个要运输的货物
            for(int j=0; j<m[v[i]].size(); j++)  //第2层for是看每个要运输的货物,下面有哪些不相容的物体,在对应回去a数组的元素看是否为之前设置的1,如果是表示不相容flag=1
                if (a[m[v[i]][j]] == 1) 
                    flag = 1;
         printf("%s\n",flag?"No":"Yes");  //如果flag为1表示不相容,如果flag为0表示想容
     }
     return 0;
}

知识总结:
1.对于需要有一个值作为关键字,然后其后对应多个值,可以设置为map类型,代码如下:

map<int,vector<int>> m;   //设置一个关键字为int类型,然后下面是一个vector的数组

2.如果用while对于某一个值cnt来循环,可以设置为

while(cnt--)
{}

3.对于给vector数组输入值时,最好提前设置好vector的长度,这样可以保证全部输入进去

         scanf("%d", &cnt);
         vector<int> v(cnt);
         for (int i = 0; i < cnt; i++) 
         {
             scanf("%d", &v[i]);     //v[i]是运输货物的编号
    
         }

1091
参考代码;

#include
using namespace std;
/*
    解题思路:
    1.让j的值从小到大开始排列
    2
*/
int fanhui(int a)
{
    int b=1;
    while(a!=0)
    {
       b*=10;
       a/=10;
    }
    return b;
}
int main()
{
    int n,j;
    cin >> n;
    for(int i=0; i<n; i++)
    {
        int temp;
        cin >> temp;
        for(j=1; j<10; j++)
        {
            if((j*temp*temp-temp)%fanhui(temp)==0)
            {

                cout << j << " " << j*temp*temp << endl;
                break;
            }
        }
        if(j==10)
            cout << "No" << endl;

    }
}

解题思路2:
1.to_string是将数字转化为字符串
2.将两个要比较的数字转化为字符串,然后分别计算其长度,然后截取
3.最后比较字符,如果相同则输出

参考代码:

#include 
#include 
using namespace std;
/*
    解题思路:

*/
int main() 
{
     int m;
     cin >> m;
     while (m--) 
     {
         int k,n;
         cin >> k;
         for (n = 1; n < 10; n++) 
         {
             int mul = n * k * k;
             string smul = to_string(mul), sk = to_string(k);
             string smulend = smul.substr(smul.length() - sk.length());
             if (smulend == sk) 
             {
                    printf("%d %d\n", n, mul);
                    break;
             }
         }
         if (n==10)
            printf("No\n");
     }
     return 0; 
}

/*

    
*/

知识总结:
1.s.substr(n)表示从s这个字符串中的第n个位置开始截取一直到最后

1092
解题思路:
1.双层for将每次的销售量相加,最后得到一个数组,就下标对应品种,元素值对应总销售量
2.找出其中最大值,然后遍历循环,如果有对应的,则直接按照要求输出输出即可

参考代码:

#include
#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    int n,m;
    cin >> n >> m;
    vector<int> a(n+1);
    for(int i=0; i<m; i++)
    {
        for(int j=1; j<=n; j++)
        {
            int temp;
            cin >>temp;
            a[j]+=temp;
        }
    }
    int max=-1;
    for(int i=1; i<=n; i++)
    {
        if(a[i]>=max)
            max=a[i];
    }
    cout << max << endl;
    int flag=1;
    for(int i=1; i<=n; i++)
    {
        if(a[i]==max)
        {
            if(flag!=1)
                cout << " ";
            cout << i;
            flag++;
        }
    }
}

对上面代码的改进:
1.如果将sum设为vector在main函数中就行
2.如果将sum设为普通数组形式,只能将其放到main函数外,否则不正确

#include 
#include 
using namespace std;
int main()
{
     int m, n, maxn=0,s;
     cin >> m >> n;
     vector<int> sum(m+1);
     for (int i = 1; i <= n; i++)
     {
         for (int j = 1; j <= m; j++)
         {
             cin >> s;
             sum[j] += s;
             maxn=max(maxn,sum[j]);
         }
     }
     cout << maxn << endl;
     int flag=1;
     for(int i=1; i<=m; i++)
     {
         if(sum[i]==maxn)
         {
              if(flag!=1)
                cout << " ";
             cout << i;
             flag++;
         }

     }
     return 0;
 }

1093
解题思路1:
1.用getline输入两个字符串
2.先相加
3.双层for,从第2开始每次与前面的相比较,如果相同则消除
4.消除2次

参考代码1:

#include
#include
using namespace std;
/*
    解题思路:

*/
int main()
{
    string a,b;
    getline(cin,a);
    getline(cin,b);
    a+=b;
    for(int i=1; i<a.length(); i++)
    {
        for(int j=0; j<i; j++)
        {
            if(a[i]==a[j])
                a.erase(i,1);
        }
    }
    for(int i=1; i<a.length(); i++)
    {
        for(int j=0; j<i; j++)
        {
            if(a[i]==a[j])
                a.erase(i,1);
        }
    }
    cout << a;
}

解题思路2:
1.设置一个数组的初始值全为0
2.以字符串的值作为下标
3.遍历循环字符串,如果字符作为下标所对应的元素值为0,就输出字符;然后在把元素值改为1

参考代码2:、

#include 
using namespace std;
/*
    解题思路:

*/
int main()
{
     string s1, s2, s;
     int a[150] = {0};
     getline(cin, s1);
     getline(cin, s2);
     s = s1 + s2;
     for (int i = 0; i < s.size(); i++)
     {
         if (a[s[i]] == 0)
            cout << s[i];
         a[s[i]] = 1;
     }
     return 0;
 }

1094
解题思路:
解题思路:
1.每次按照k个连续的数取截取字符串,如果是素数就直接输出,否则最后输出404

参考代码:

#include
#include
#include
using namespace std;
/*

*/
bool fanhui(int a)
{
    for(int i=2; i<sqrt(a); i++)
        if(a%i==0)
            return false;
    return true;
}
int main()
{

    string s;
    int l,k,i;
    cin >> l >> k >> s;
    for(i=0; i<=s.length()-k; i++)
    {
        stringstream ss;
        int a;
        string temp;
        temp=s.substr(i,k);
        ss << temp;
        ss >> a;
        if(fanhui(a))
        {
            cout << a;
            return 0;
        }
    }
    if(i>s.length()-k)
        cout << 404 << endl;
    return 0;
}

以上代码改进:

#include
#include
using namespace std;
bool fanhui(int a)
{
    if(a==0 || a==1)
        return false;
    for(int i=2; i<sqrt(a); i++)
        if(a%i==0)
            return false;
    return true;
}
int main()
{
    string s;
    int l,k;
    cin >> l >> k >> s;
    for(int i=0; i<=l-k; i++)
    {
        string a=s.substr(i,k);
        int q=stoi(a);  //改进在这里
        if(fanhui(q))
        {
            cout << a;  //注意这里是输出字符串,对于0002,如果输出数字是2,但是题中要求输出0002
            return 0;
        }
    }
    cout << 404 << endl;
    return 0;
}

知识总结:
1.stoi将字符串转化为整数

int q=stoi(a);  //改进在这里

1095
解题思路:
1.设置结构数组v,输入相关信息
2.for循环嵌套if-else语句:
1.输入num
2.根据num不同的值对应不同的操作:
1.num==1:
1.按要求先输出一行
2.通过for循环,对应于原结构数组;如果满足条件,则将对应结构压入新的结构数组ans中
3.排序+输出
4.如果ans的长度为0,则输出NA
2.num ==2
1.设置cnt == o, sum == 0
2.按要求输出一行
3.通过循环,如果找到对应的考场,则统计人数和总分
4.如果人数不为0,则输出人数和总分,否则,输出NA
3.num == 3
1.设置string类型date
2.按要求输出一行
3.新结构site的数组ans
4.通过循环找出,日期对应得,并截取考场字符串,接统计人数
5.map中的关键字和元素值对应到结构数组ans中
6.排序+输出
7.ans长度为0,输出NA

参考代码:

#include 
#include 
#include 
#include 
using namespace std;
struct stu   //准考证和成绩的一个结构
{
     string id;
     int sco;
};

struct site   //考场字符串和人数的一个结构
{
     string siteId;
     int cnt;
};

bool cmp1(const stu a, const stu b)   //如果成绩相同,则按照id的增序输出;否则按照,成绩的降序输出
{
 return a.sco == b.sco ? a.id < b.id : a.sco > b.sco;
}

bool cmp2(const site &a, const site &b)   //如果人数相同,则按照考场字符串的升序输出;否则按照,人数的降序输出
{
 return a.cnt == b.cnt ? a.siteId < b.siteId : a.cnt > b.cnt;
}

int main()
{
     int n, k;
     cin >> n >> k;
     vector<stu> v(n);    //结构数组

     for (int i = 0; i < n; i++)
        cin >> v[i].id >> v[i].sco;  //将信息输入至结构数组

     for (int i = 1; i <= k; i++)
     {
         int num;
         scanf("%d", &num);
         if (num == 1)
         {
             string level;
             cin >> level;   
             printf("Case %d: %d %s\n", i, num, level.c_str());  //level.c_str()专用于printf的输出
             vector<stu> ans;  //定义一个vector的新结构ans
             for (int i = 0; i < n; i++)    //通过for循环,对应于原结构数组;如果满足条件,则将对应结构压入新的结构数组ans中
             {
                 if (v[i].id[0] == level[0])
                    ans.push_back(v[i]);
             }
             sort(ans.begin(), ans.end(),cmp1);  //排序
             for (int i = 0; i < ans.size(); i++)   //输出
             printf("%s %d\n", ans[i].id.c_str(), ans[i].sco);
             if (ans.size() == 0) printf("NA\n");  //如果ans长度为0,则输出NA
         }
         else if (num == 2) 
         {
             int cnt = 0, sum = 0;  //设置cnt=0,sum=0
             int siteId;
             cin >> siteId;   
             printf("Case %d: %d %d\n", i, num, siteId);
             for (int i = 0; i < n; i++)  //通过循环,如果找到对应的考场,则统计人数和总分
             {
                 if (v[i].id.substr(1, 3) == to_string(siteId)) 
                 {
                     cnt++;
                     sum += v[i].sco;
                 }
             }
             if (cnt != 0)    //如果人数不为0,则输出人数和总分
                printf("%d %d\n", cnt, sum);
             else           //否则,输出NA
                printf("NA\n");
         } 
         else if (num == 3) 
         {
             string date;
             cin >> date;
             printf("Case %d: %d %s\n", i, num, date.c_str());
             vector<site> ans;     //新结构site的数组ans
             unordered_map<string, int> m;
             for (int i = 0; i < n; i++)   //通过循环找出,日期对应得,并截取考场字符串,接统计人数
             {
                 if (v[i].id.substr(4, 6) == date) 
                 {
                     string tt = v[i].id.substr(1, 3);
                     m[tt]++;
                 }
             }
             for (auto it : m)  //将map中的关键字和元素值对应到结构数组ans中
                ans.push_back({it.first, it.second});
             sort(ans.begin(), ans.end(),cmp2);
             for (int i = 0; i < ans.size(); i++)
                printf("%s %d\n", ans[i].siteId.c_str(), ans[i].cnt);
             if (ans.size() == 0) 
                    printf("NA\n");
         }
     }
     return 0;
 }

知识总结:
1.用printf输出string类型字符串

#include
#include
#include
using namespace std;
int main()
{
    string s;
    cin >> s;
    printf("%s\n",s);     //string类型的变量如果用printf输出,就不对
    printf("%s",s.c_str());  //对于printf,只能用c_str()*/
}

2.c++11新特性,直接输出v的字符串

#include
#include
#include
using namespace std;
int main()
{
    vector<int> v={1,2,3,4};
    for(auto i:v)
        cout << i;

}

3.c++11新特性,将map的关键字和元素值对应到结构数组中

#include
#include
#include
#include
using namespace std;
struct site   //考场字符串和人数的一个结构
{
     string siteId;
     int cnt;
};  
int main()
{ 
    vector<site> ans;
    unordered_map<string, int> m;    
    for (auto it : m)
        ans.push_back({it.first, it.second});

}

4.map和unordered_map的区别:
map:

优点:

有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高
缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间

适用处:对于那些有顺序要求的问题,用map会更高效一些

unordered_map:

优点: 因为内部实现了哈希表,因此其查找速度非常的快
缺点: 哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
总结:

内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。
但是unordered_map执行效率要比map高很多
对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的

注意事项:

  1.         printf("Case %d: %d %s\n", i, num, level.c_str());  //level.c_str()专用于printf的%s输出
    
printf("%s %d\n",ans[i].id.c_str(),ans[i].sco)向比于cout << ans[i].id << " " << ans[i].sco << endl节省时间
printf("%s %d\n",ans[k].siteId.c_str(),ans[k].cnt)相比于cout << ans[k].siteId << " " << ans[k].cnt << endl;节省时间

你可能感兴趣的:(pat,乙级题解)