天天快樂編程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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM