数学.


*サムネイルはThumbnail-Maker by oneookです.

数学2の実施内容


「数学2」の問題は大体少数の問題と対陣法の問題から構成されている.
個人的には、グラフィック制作の問題に比べて、実現が簡潔で、難易度がやや低いと思います.
数学の知識が必要な問題もあるが、どうすればいいかさえ分かれば、実施自体は難しくない.

1009角桁数の逆和

#include <iostream>
using namespace std;
 
int main()
{
    int num;
    int rev;
    int sum;
 
    cin >> num;
 
    while (num > 0)
    {
        rev = 0;
        sum = 0;
 
        while (num > 0)
        {
            rev *= 10;
            rev += num % 10;
            sum += num % 10;
            num /= 10;
        }
 
        cout << rev << " " << sum << endl;
 
        cin >> num;
    }    
 
    return 0;
}
  • は最初にデジタル反転直接出力を実現し、結果0が一番前に現れ(ex>100反転001に出力)、int revに変更して値をデジタルに格納した.
  • 2811素数と合成数

    #include <iostream>
    using namespace std;
     
    bool isPrimeNumber(int n)
    {
        if (n == 1)
        {
            return false;
        }
     
        for (int i = 2; i <= n / i; i++)
        {
            if (n % i == 0)
            {
                return false;
            }
        }
     
        return true;
    }
     
    int main()
    {
        int num[5];
     
        for (int i = 0; i < 5; i++)
        {
            cin >> num[i];
        }
     
        for (int i = 0; i < 5; i++)
        {
            if (num[i] == 1)
            {
                cout << "number one" << endl;
            }
            else if (isPrimeNumber(num[i]))
            {
                cout << "prime number" << endl;
            }
            else
            {
                cout << "composite number" << endl;
            }
        }
     
        return 0;
    }
  • の最大値は10億なので、2から数字を入力するまで、数字全体が小数か小数かを判断するには時間制限がかかる可能性があるので、入力数字の平方根を確認するしかなく、時間を短縮できます.
  • 1740小数

    #include <iostream>
    using namespace std;
     
    bool isPrimeNumber(int n)
    {
        if (n == 1)
        {
            return false;
        }
     
        for (int i = 2; i <= n / i; i++)
        {
            if (n % i == 0)
            {
                return false;
            }
        }
     
        return true;
    }
     
    int main()
    {
        int M;
        int N;
        int sum = 0;
        int min = 10000;
     
        cin >> M >> N;
     
        for (int i = M; i <= N; i++)
        {
            if (isPrimeNumber(i))
            {
                sum += i;
                if (min > i)
                {
                    min = i;
                }
            }
        }
     
        if (sum == 0)
        {
            cout << -1 << endl;
        }
        else
        {
            cout << sum << endl << min << endl;
        }
     
        return 0;
    }
  • 入力数字の範囲は1から10000までであり、以前の問題で体現されたisPrimeNumber(int n)に沿っている.
  • 1901小数を取得

    #include <iostream>
    using namespace std;
     
    bool isPrimeNumber(int n)
    {
        if (n <= 1)
        {
            return false;
        }
      
        for (int i = 2; i <= n / i; i++)
        {
            if (n % i == 0)
            {
                return false;
            }
        }
      
        return true;
    }
     
    int main()
    {
        int N;
        int M[100];
     
        cin >> N;
        for (int i = 0; i < N; i++)
        {
            cin >> M[i];
        }
     
        for (int i = 0; i < N; i++)
        {
            if (isPrimeNumber(M[i]))
            {
                cout << M[i] << endl;
     
                continue;
            }
     
            int diff = 1;
            int small = 0;
            int large = 0;
            while (small == 0 && large == 0)
            {
                if (isPrimeNumber(M[i] - diff))
                {
                    small = M[i] - diff;
                }
     
                if (isPrimeNumber(M[i] + diff))
                {
                    large = M[i] + diff;
                }
     
                diff++;
            }
     
            if (small > 0 && large > 0)
            {
                cout << small << " " << large << endl;
            }
            else if (small > 0)
            {
                cout << small << endl;
            }
            else if (large > 0)
            {
                cout << large << endl;
            }
        }
     
        return 0;
    }

    2813少数

    #include <iostream>
    using namespace std;
     
    void findPrime(int N, int* num)
    {
        num[1] = 1;
        for (int i = 2; i <= N / i; i++)
        {
            if (num[i] == 0)
            {
                for (int j = i * 2; j <= N; j += i)
                {
                    num[j] = 1;
                }
            }
        }
    }
     
    int main()
    {
        int M;
        int N;
        int num[2000001] = { 0 };
     
        cin >> M >> N;
     
        findPrime(N, num);
     
        int cnt = 0;
        for (int i = M; i <= N; i++)
        {
            if (num[i] == 0)
            {
                cnt++;
            }
        }
     
        cout << cnt << endl;
     
        return 0;
    }
  • 以前の問題のように、入力された値と範囲がずっと大きいため、同じように実行する時間が長すぎます.
  • MからNまでの範囲のみ小数を判別せず、エラトステネスのふるいを実施し、1からNまでの範囲を対象として小数を判別し、MからNまでの小数を数え、数字が大きく、範囲が広いと速度が速くなる.
  • 2814バイナリ

    #include <iostream>
    using namespace std;
     
    int main()
    {
        char bi[31] = { 0 };
        int dec = 0;
     
        cin >> bi;
     
        for (int i = 0; i < 30; i++)
        {
            if (bi[i] == 0)
            {
                break;
            }
     
            dec *= 2;
            dec += (bi[i] - '0');
        }
     
        cout << dec << endl;
     
        return 0;
    }
  • 入力のバイナリ数は最大30ビットであり,int,long,long longともに不可能であるためchar配列を用いた.
  • 1534 10進数2、8、16進数

    #include <iostream>
    using namespace std;
     
    int main()
    {
        int dec;
        int B;
        char arr[20];
     
        cin >> dec >> B;
     
        int index = 0;
        while (dec > 0)
        {
            int num = dec % B;
            char c;
            if (num < 10)
            {
                c = '0' + num;
            }
            else
            {
                c = 'A' + num - 10;
            }
            arr[index++] = c;
     
            dec /= B;
        }
     
        for (int i = index - 1; i >= 0; i--)
        {
            cout << arr[i];
        }
        cout << endl;
     
        return 0;
    }
  • 入力最大値は100000で、変換には最大17ビットが必要です.(10進数100000=2進数000110011010000)メモリ制限にも余裕があるのでchar配列サイズを20と定義します.
  • 3106変換アレイ

    #include <iostream>
    using namespace std;
     
    int main()
    {
        int A;
        char S[64];
        int B;
        char arr[64];
     
        for (int i = 0; i < 100; i++)
        {
            cin >> A;
            if (A == 0)
            {
                break;
            }
            cin >> S >> B;
     
            long long dec = 0;
            for (int j = 0; j < 64; j++)
            {
                if (S[j] == 0)
                {
                    break;
                }
     
                int num;
                if (S[j] >= '0' && S[j] <= '9')
                {
                    num = S[j] - '0';
                }
                else
                {
                    num = S[j] - 'A' + 10;
                }
     
                dec *= A;
                dec += num;
            }
     
            if (dec == 0)
            {
                cout << '0' << endl;
                continue;
            }
     
            int index = 0;
            while (dec > 0)
            {
                int num = dec % B;
                if (num < 10)
                {
                    arr[index++] = num + '0';
                }
                else
                {
                    arr[index++] = (num - 10) + 'A';
                }
     
                dec /= B;
            }
     
            for (int i = index - 1; i >= 0; i--)
            {
                cout << arr[i];
            }
            cout << endl;
        }
     
     
        return 0;
    }
  • の最大値は2^63-1であるため、配列サイズは64と定義され、変換アレイ法では中間ステップの10進数に変換するために長い変数が用いられる.