天天快乐编程2020寒假提高班(临海)作业题解

1.5211: 18岁

你到18岁需要过几天,当然你的18岁生日还有可能不存在,比如你是今年2月29日出生的,那你每四年就只能过一个生日,18不是4的倍数,所以没生日可过。

我们用变量sum表示我们到18岁的天数,接下来就只需要解决闰年还有平年的问题了,你是3月出生的,那今年闰年和你无关啊,你是二月前才有关联,所以二月之后生日的你需要看的是下一年是不是闰年。也就是你的1岁生日不是因为你出生的那年是闰年就是366天,而是因为1.今年是闰年,而且你是3月前出生。2.明年是闰年,而且你是3月后(包含)出生

两个数字之间的-可以用一个char字符读入

#include <bits/stdc++.h>
using namespace std;

//判断闰年函数
bool isLeapYear(int y)
{
    if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
        return true;
    return false;
}

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int y, m, d;
        char c;
        //读入年月日,中间用char隔开
        cin >> y >> c >> m >> c >> d;
        //总日子数sum
        int sum = 0;
        //2.29没生日输出
        if (m == 2 && d == 29)
        {
            cout << "-1" << endl;
            continue;
        }
        //3月之后(包括)看下一年
        if (m > 2)
            y++;
        //循环18年
        for (int i = y; i < y + 18; i++)
        {
            if (isLeapYear(i))
                sum += 366;
            else
                sum += 365;
        }
        cout << sum << endl;
    }
    return 0;
}
View Code

2.1060: 鹊桥相会

这个题目看起来很复杂,但是需要自己不去关注那些无用的条件。因为喜鹊只能往一个方向飞,还想带着牛郎往织女方向飞,天和是正方向,所以喜鹊的位置必须是负数或牛郎所在的位置0,喜鹊的速度必须是正数才飞对了方向。之后就是路程s是w*1000-t(因为t是负数,减去变正数),速度是v,时间t=s/v,取最小即可

你可以估算一下最大时间,就是w=1000,t=1000,v=1,也就是10001000,我只要设置一个大于他的数就可以作为最大值了

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int w, n;
    while (cin >> w >> n, w || n)
    {
        //设置一个到达不了时间,也就是最大时间+1
        int minTime = 10001001;
        while (n--)
        {
            int t, v;
            cin >> t >> v;
            if (t <= 0 && v > 0)
            {
                //时间=路程/速度
                int time = (w * 1000 - t) / v;
                if (time < minTime)
                {
                    minTime = time;
                }
            }
        }
        if (minTime == 10001001)
            cout << "Can't Solve\n";
        else
            cout << minTime << "\n";
    }
    return 0;
}
View Code

3.5292: 游戏之购物

我们可以先计算出商品总额,之后先使用满减优惠,再使用红包,使用需要注意自己的优惠券够不够,当然超过了不能不能支付负数

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int n, p, q, sum = 0;
        cin >> n >> p >> q;
        for (int i = 0,x; i < n; i++)
        {
            cin >> x;
            sum += x;
        }
        //discount优惠,表示满减优惠金额
        int  dis = (sum / 400) * 50;
        //可满减比拥有的少
        if (p < dis)
            sum -= p;
        else
            sum -= dis;
        //使用红包优惠,金额比红包少
        if (sum < q)
            sum = 0;
        else
            sum -= q;
        cout << sum << endl;
    }
    return 0;
}
View Code

4.5857: 桃子的高低音

这个题目简单描述,就是一个高音就是他比两边的都高,那么我只要用每个数比较就好了,第一个和最后一个不会是高音

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        for (int i = 0; i < n; i++)
            cin >> a[i];
        int num=0;
        //两边均比中间大,满足统计
        for (int i = 1; i < n - 1; i++)
            if (a[i] > a[i - 1] && a[i] > a[i + 1])
                num++;
        cout << num << endl;
    }
}
View Code

5.3016: 两圆位置关系

两圆的位置关系,和两圆点距离有关,关系如下:

 

 

学好编程之前一定要学好数学,加油~

但是距离算出来是一个浮点数,直接比较可能会出问题,我们直接对其进行平方,这样也不需要考虑谁大谁小了,不需要取绝对值了

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int x1, y1, r1;
    while (cin >> x1 >> y1 >> r1)
    {
        int x2, y2, r2;
        cin >> x2 >> y2 >> r2;
        int D = (r1 + r2) * (r1 + r2), d = (r1 - r2) * (r1 - r2);
        double len = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
        int ans;
        //以下是if嵌套的,注意!
        if (D == len || d == len)
        {
            //两圆心距离与半径之和或之差相等
            ans = 1;
        }
        else if (len > D)
        {
            //两圆心距离大于半径之和
            ans = 2;
        }
        else if (len < d)
        {
            //两圆心距离小于于半径之差
            ans = 3;
        }
        else
        {
            ans = 4;
        }
        cout << ans << endl;
    }
    return 0;
}
View Code

6.5044: 在霍格沃茨找零钱

十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西可。和时间是不是很像,1小时是60分,1分钟是60秒。这都属于进制转换题目,我们先取余,再取整抛弃这一位就可以了

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int p[3], a[3];
    char b;
    cin >> p[0] >> b >> p[1] >> b >> p[2] >> a[0] >> b >> a[1] >> b >> a[2];
    //应付的总纳特
    int sum1 = p[0] * 17 * 29 + p[1] * 29 + p[2];
    //实付的总纳特
    int sum2 = a[0] * 17 * 29 + a[1] * 29 + a[2];
    int sum = sum2 - sum1, ans[3];
    //钱没带够先输出负号
    if (sum < 0)
    {
        cout << "-";
        sum = -sum;
    }
    //获取纳特数
    ans[2] = sum % 29;
    //丢去纳特数
    sum = sum / 29;
    //获取银西可数
    ans[1] = sum % 17;
    //丢去银西可数
    sum = sum / 17;
    //sum即为加隆数
    ans[0] = sum;
    cout << ans[0] << "." << ans[1] << "." << ans[2] << endl;
}
View Code

7.4020: 有道水题

获取每一位还是需要进制转换。但是也可以直接用字符串来做这个题目,记得减去字符0

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        string s;
        cin >> s;
        int sum = 0;
        for (int i = 0; s[i]; i++)
            sum += s[i] - '0';
        //sum1代表从第1位到这一位总和
        //flag为0表示不存在
        int sum1 = 0, flag = 0;
        for (int i = 0; s[i]; i++)
        {
            sum1 += s[i] - '0';
            //直接除以2下取整会出问题
            if (sum1 + sum1 == sum)
            {
                //存在结束循环
                flag = 1;
                break;
            }
        }
        if (flag)
            cout << "YES\n";
        else
            cout << "NO\n";
    }
}
View Code

8.5128: 就是要62

还是进制转换,2进制转10进制。11的二进制表示是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,也就是第i位要乘上2^(len-1)

获取每一位的进制转换我们是倒过来,这个我们可以正过来,保证*2的次数对就可以了

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    //读入要进行转换的字符串s
    cin >> s;
    //设置变量t去保存这个答案
      int t = 0;
    for (int i = 0; s[i]; i++)
    {
        t = t * 2 + (s[i] - '0');
    }
    cout << t << "\n";
}
二进制转10进制

之后我们要把十进制转换为一位的一位,这样会帮我们倒过来

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    //读入要进行转换的字符串s
    while (cin >> s)
    {
        //设置变量t去保存这个答案
        int t = 0;
        for (int i = 0; s[i]; i++)
        {
            t = t * 2 + (s[i] - '0');
        }
        int len = 0;
        //10^9就是1后面有9个0,是十位
        int a[10];
        while (t)
        {
            //存储当前位
            a[len++] = t % 10;
            //丢弃当前位
            t /= 10;
        }
        int num = 0;
        for (int i = 1; i < len; i++)
        {
            //是26,字符串被倒过来了
            if (a[i - 1] == 6 && a[i] == 2)
                num++;
            //是62
            if (a[i - 1] == 2 && a[i] == 6)
                num++;
        }
        cout << num << "\n";
    }
}
View Code

9.1091: JudgeOnline

这个题目就是判断字符,你可能会忘记了tab符'\t',因为要读取空格,请整行读入

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    //有空格,直接getline
    while (getline(cin, s))
    {
        for (int i = 0; s[i]; i++)
        {
            if (s[i] == '<')
                cout << "&lt;";
            else if (s[i] == '>')
                cout << "&gt;";
            else if (s[i] == ' ')
                cout << "&nbsp;";
            else if (s[i] == '\t')
                cout << "&#9;";
            else
                cout << s[i];
        }
        cout << "\n";
    }
}
View Code

10.5858: 桃子的游戏

题意其实也蛮简单的,就是三个人初始是x、y和z,之后每个时间+i,然后按照两个条件进行加减点数,但是是一个三重循环

第一重循环是T组,第二重是q组,第三重是t的枚举

记得使用long long,1e5+(1+1e4)/2*1e4超过了int

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int T;
    cin >> T;
    //有T组
    while (T--)
    {
        int x, y, z;
        //读入三个初始值
        cin >> x >> y >> z;
        int q;
        cin >> q;
        while (q--)
        {
            int n;
            //读入这次查询的时间
            cin >> n;
            //用X、Y和Z代表他们的当前值,但是这个值会超过int
            long long X = x, Y = y, Z = z;
            for (int i = 1; i <= n; i++)
            {
                //每个人都可以得到i点
                X += i, Y += i, Z += i;
                if (Y >= 3)
                {
                    //小明给桃子3点
                    Y -= 3;
                    X += 3;
                }
                if (Z >= 6)
                {
                    //小强给桃子6点
                    Z -= 6;
                    X += 6;
                }
            }
            //最后是否比两个人的大
            if (X > Y && X > Z)
                cout << "Yes\n";
            else
                cout << "No\n";
        }
    }
    return 0;
}
View Code

11.5265: 围棋入门

如果这个棋子是白棋,那么他周围这四个就有可能要被你输出。所以去找到所有的白棋,看看其是否要输出

还有一个事情很麻烦,就是边界,我们不能越界,那我们可以将其第0行第0列空出来

行号从小到大的顺序输出,如果行号相同,则按照列号从小到大的顺序,这个我们用一个数组去记录我们的答案

#include <bits/stdc++.h>
using namespace std;
int ans[25][25];
char s[25][25];
//定义方向数组dir
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int main()
{
    //读入第一行,存储从s[1][1]开始
    while(cin>>(s[1]+1))
    {
        int n=19;
        for(int i=2;i<=n;i++)
        {
            //读入第i行,存储从s[i][1]开始
            cin>>(s[i]+1);
        }
        //清空答案
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                //枚举每一个棋子,是W,需要找四个棋子
                if(s[i][j]=='W')
                {
                    for(int k=0;k<4;k++)
                    {
                        int x=i+dir[k][0];
                        int y=j+dir[k][1];
                        //是.代表可以放置
                        if(s[x][y]=='.')ans[x][y]=1;
                    }
                }
            }
        }
        //假设白棋已经被围住
        int flag=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                //枚举每一个坐标看是否需要输出,这样可以保证先行再列
                if(ans[i][j])
                {
                    cout<<i<<" "<<j<<"\n";
                    flag=0;
                }
            }
        }
        if(flag)cout<<"YuYu Wins!\n";
    }
}
View Code

12.1437: Zigzag

是不是和蛇形矩阵有点像,但是这个题目需要自己去设计循环,是一样的斜线,但是这个题还有方向,对角线可能是从左下到右上,也有可能是右上到左下

所以我们还需要借助一个变量去控制现在是哪个方向

flag=1代表左下到右上,也是一开始的方向,flag=-1代表从右上到左下,然后让其循环

最后的右下角重新找规律输出

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n, a[25][25];
    while (cin >> n ,n)
    {
        int s = 1, flag = 1;
        //对角线和为i
        for (int i = 0; i < n; i++)
        {
            //左下开始是0
            for (int j = 0; j <= i; j++)
            {
                //左下到右上填充,否则颠倒填充
                if (flag == 1)
                    a[i - j][j] = s++;
                else
                    a[j][i - j] = s++;
            }
            flag = -flag;
        }
        //右下角,最后是2n-2
        for (int i = n; i < n + n-1; i++)
        {
            //左下开始是n-i
            for (int j = i-n+1; j < n; j++)
            {
                cout<<j<<" "<<i-j<<"\n";
                if (flag == 1)
                    a[i - j][j] = s++;
                else
                    a[j][i - j] = s++;
            }
            flag = -flag;
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (j != 0)
                    cout << " ";
                printf("%-3d", a[i][j]);
            }
            cout << endl;
        }
        cout<<"\n";
    }
    return 0;
}
View Code

13.1438: 螺旋形

这个题目就麻烦了,之前你们没有见过,但是我们可以思考一下,每次我们都是四个操作,向右,向下,向左,向上,一圈一圈往里填。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n, a[25][25];
    while (cin >> n, n)
    {
        //n是1没有四个方向特判掉
        if (n == 1)
            a[0][0] = 1;
        else
        {
            //i和j代表当前要填充的坐标,now是当前要填的数,N是最大可以填的数字
            int i = 0,j = 0, now = 1, N = n * n;
            //设置四个上下左右变量,代表当前所在位置
            int U = 0, D = n - 1, L = 0, R = n - 1;
            while (now <= N)
            {
                //向右走,列++
                while (j < R && now <= N)
                {
                    a[i][j] = now++;
                    j++;
                }
                //向下走,行++
                while (i < D && now <= N)
                {
                    a[i][j] = now++;
                    i++;
                }
                //向左走,列--
                while (j > L && now <= N)
                {
                    a[i][j] = now++;
                    j--;
                }
                //向上走,行--
                while (i > U && now <= N)
                {
                    a[i][j] = now++;
                    i--;
                }
                //缩一圈,i和j各加1
                i++,j++;
                //缩一圈,U到了下一行,D到上一行,L到下一列,R到前一列
                U++, D--, L++, R--;
                //填充最后一个数
                if (now == N)
                    a[i][j] = now++;
            }
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (j != 0)
                    cout << " ";
                printf("%-3d", a[i][j]);
            }
            cout << endl;
        }
        cout << "\n";
    }
}
View Code

这篇博客还有两种写法,你需要推算出下标所对应的数字或者按照循环的方式去解答

14.3297: 名侦探柯南-破解死亡讯息 

需要读懂这个题目,拿到字符s[i]代表的是我们这一密码段有s[i]-'A'个字符,这s[i]-'A'个字符要进一步解码,变为数字求和

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    while (cin >> s)
    {
        for (int i = 0; s[i]; i++)
        {
            //sum为当点段解码,c代表当前密码段有几个
            int sum = 0, c = s[i] - 'A' + 1;
            for (int j = i; j < i + c; j++)
                sum = sum + s[j] - 'A' + 1;
            cout << sum;
            //下一次访问i+c,因为还要执行i++,回退一个
            i = i + c - 1;
        }
        cout << "\n";
    }
    return 0;
}
View Code

15.5168: 报时助手

一个比较复杂的模拟题,我们需要考虑各种情况,这个题目要先思考好在再动手

我只是提供一种代码实现,你也可以自己想一个思路去避所有可能产生的bug,从而AC题目

#include <bits/stdc++.h>
using namespace std;

string s[25] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"};
int main()
{
    int m, n;
    cin >> m >> n;
    //m比20小,我们已经有了输出答案
    if (m <= 20)
        cout << s[m];
    else
    {
        //将其拆成20+(m-20)进行输出
        cout << s[20] << " " << s[m - 20];
    }
    //是整点直接输出
    if (n == 0)
    {
        cout << " o'clock";
    }
    else if (n <= 20)
    {
        //小于20直接输出
        cout << " " << s[n];
    }
    else if (n < 30)
    {
        //将其拆成20+(n-20)进行输出
        cout << " " << s[20] << " " << s[n - 20];
    }
    else if (n < 40)
    {
        //将其拆成30+(n-30)进行输出
        cout << " thirty";
        //n-30是0不能输出
        if (n - 30)
            cout << " " << s[n - 30];
    }
    else if (n < 50)
    {
        //将其拆成40+(n-40)进行输出
        cout << " forty";
        //n-40是0不能输出
        if (n - 40)
            cout << " " << s[n - 40];
    }
    else
    {
        //将其拆成50+(n-50)进行输出
        cout << " fifty";
        //n-50是0不能输出
        if (n - 50)
            cout << " " << s[n - 50];
    }
    cout << "\n";
    return 0;
}
View Code

16.5136: 隧道有多长

这个题目也不难,就是你需要统计一个字符串中间有多少个连续的'#',当然也会不存在,所以最小值这个特别注意

我们可以一重循环去统计

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    while (cin >> s)
    {
        //用mi和mx来记录答案,t来记录当前的长度
        int mi = 0, mx = 0, t = 0;
        for (int i = 0; s[i]; i++)
        {
            //是'#'需要将隧道长度+1
            if (s[i] == '#')t++;
            //其他需要统计答案的情况
            //1.不是隧道 2.最后一个字符了
            if (s[i] == '*' || s[i + 1] == 0)
            {
                //最小值不是0取小
                if (mi)
                {
                    //t也不是0才能更新
                    if (t)
                        mi = min(mi, t);
                }
                else
                    mi = t;
                //最大值不是0,取大
                if (mx)
                {
                    mx = max(mx, t);
                }
                else
                    mx = t;
                t = 0;
            }
        }
        cout << mi << " " << mx << endl;
    }
    return 0;
}
View Code

17.3212: Pig在哪里

这个题目也很简单,你需要判断连续的三个字符是不是pig

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int n;
        string s;
        cin>>n>>s;
        int num=0;
        //从可以访问i-2开始
        for(int i=2;i<s.length();i++)
        {
            if(s[i-2]=='p'&&s[i-1]=='i'&&s[i]=='g')
                num++;
        }
        cout<<num<<"\n";
    }
    return 0;
}
View Code

18.3134: 渊子赛马修改版

课堂上贪心的一个扩展,这个题目还是有一定难度的,允许平局我就得考虑这把怎么要平局

1.最好的最差都可以,那就赢了2.渊子最好的马比对手差,直接用下等马输掉3.相等,如果最差的马太菜,输掉,否则平局

代码会比思想更直观些

#include<bits/stdc++.h>
using namespace std;
int a[10005],b[10005];
int main()
{
    int n;
    while(cin>>n,n)
    {
        for(int i=0; i<n; i++)cin>>a[i];
        //渊子的马从小到大排序
        sort(a,a+n);
        for(int i=0; i<n; i++)cin>>b[i];
        //对手的马从小到大排序
        sort(b,b+n);
        //aL(a数组左端点)是渊子当前最差的马的下标
        //aR(a数组右端点)是渊子当前最好的马的下标
        //bL是对手当前最差的马的下标,aR是对手当前最好的马下标
        int aL=0,bL=0,aR=n-1,bR=n-1;
        //ans代表当前的净胜场数
        int ans=0;
        for(int i=0; i<n; i++)
        {
            if(a[aL]>b[bL])
            {
                //渊子最差的马比对手的还好,直接比掉
                aL++,bL++,ans++;
            }
            else if(a[aR]>b[bR])
            {
                //渊子最好的马比对手的还好,也可以直接比掉
                aR--,bR--,ans++;
            }
            else if(a[aR]<b[bR])
            {
                //渊子最好的马比对手差,直接用下等马输掉
                aL++,bR--,ans--;
            }
            else if(a[aR]==b[bR])
            {
                //最好的马相等,那么我需要考虑一下
                //渊子最差的马比对手好的马差了,算了,用差马输出了
                if(a[aL]<b[bR])ans--;
                //如果相等呢,那就是渊子剩下的马全一样了,直接平局就行
                //!!!这个平局很重要,没有净胜减少
                aL++,bR--;
            }
        }
        //净胜场数为正,为0,为负分别对应三种情况
        if(ans>0)
            cout<<"Win\n";
        else if(ans==0)
            cout<<"Draw\n";
        else cout<<"Lost\n";
    }
    return 0;
}
View Code

19.5725: 营养膳食

贪心,按照脂肪指数从高到低排序,这种种类还可以选择就选择,且只能选m个。

#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
struct T
{
    int ai, bi;
} a[N];
int num[N];
bool cmp(T a, T b)
{
    return a.ai > b.ai;
}
int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 1; i <= k; i++)
        cin >> num[i];
    for (int i = 0; i < n; i++)
        cin >> a[i].ai >> a[i].bi;
    //按照ai进行排序,先吃脂肪指数高的
    sort(a, a + n, cmp);
    int sum = 0;
    //进来选食物
    for (int i = 0; i < n; i++)
    {
        //当前类别可选
        if (num[a[i].bi])
        {
            //把脂肪指数加上
            sum = sum + a[i].ai;
            //这种种类的少一份
            num[a[i].bi]--;
            m--;
            if (!m)break;
        }
    }
    cout << sum;
    return 0;
}
View Code

20.3457: 最小新数

又回到了之前的进制转换,你可以得到0~9出现的位数

这个题目也是贪心,你需要从小开始输出,但是你不能直接先输出0,一个数不能从0开始,所以你要先输出一个。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    while(cin>>s)
    {
        //看0~9的出现次数
        int a[10]={0};
        for(int i=0;s[i];i++)
            a[s[i]-'0']++;
        //先输出一个非0最小数字
        for(int i=1;i<10;i++)
        {
            if(a[i]>0)
            {
                cout<<i;
                a[i]--;
                break;
            }
        }
        //继续从0开始,从小到大输出
        for(int i=0;i<10;i++)
        {
            while(a[i])
                cout<<i,a[i]--;
        }
        cout<<endl;
    }
    return 0;
}
View Code

21.6149: 因子个数排序

排序我们可以直接使用sort,那记录一个因子我们还需要结构体吗?
可以不用,因为排序的速度很快,所以你的函数调用次数也有限,所以我们可以把因子个数直接写在cmp函数里。
怎么求因子个数,循环1~n,看看是不是因子,但是不能通过这个题目,因为数据太大了,不能在求因子浪费太多时间。其实我们找到1个因子其实就能找到2个,找到了因子i那么还有因子n/i,但是完全平方数(这个数等于两个相同的数相乘,比如4、9、16)只能计算一次,需要特殊判断。所以我们只要找到sqrt(n)就可以了。
#include <bits/stdc++.h>
using namespace std;
int a[205];
//计算因子个数函数
int cal(int n)
{
    //sqrt是浮点数,可能会有问题,+0.5不会出问题
    int x = sqrt(n + 0.5);
    //因为你最多算到一半,算出来因子i,那么n/i也是
    int s = 0;
    for (int i = 1; i <= x; i++)
    {
        if (n % i == 0)
        {
            //3*3=9,这种完全平方特殊处理下
            if (i * i == n)
                s++;
            else
                s += 2;
        }
    }
    return s;
}
int cmp(int s, int t)
{
    //分别计算两数因子数
    int s1 = cal(s), s2 = cal(t);
    //相等,比较两个大小
    if (s1 == s2)
        return s > t;
    return s1 > s2;
}
int main()
{
    int n;
    while (cin >> n)
    {
        for (int i = 0; i < n; i++)
            cin >> a[i];
        sort(a, a + n, cmp);
        for (int i = 0; i < n - 1; i++)
            cout << a[i] << " ";
        cout << a[n - 1] << "\n";
    }
    return 0;
}
View Code

22.3148: 按1的个数排序

这个题依旧可以直接sort,然后我们也在cmp中统计1的个数,当然你也可以用结构体实现
#include<bits/stdc++.h>
using namespace std;
string s[100];
int cmp(string s,string t)
{
    //分别找到两个字符串1的个数
    int s1=0,s2=0;
    for(int i=0;s[i];i++)
        if(s[i]=='1')s1++;
    for(int i=0;t[i];i++)
        if(t[i]=='1')s2++;
    //1的个数相等,按照s和t字典序排序
    if(s1==s2)return s<t;
    return s1<s2;
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>s[i];
    sort(s,s+n,cmp);
    for(int i=0;i<n;i++)
        cout<<s[i]<<endl;
    return 0;
}
View Code

 

posted @ 2020-02-11 22:55  暴力都不会的蒟蒻  阅读(543)  评论(0编辑  收藏  举报