第15回蘭橋杯シミュレーション大会 グループB(後期) C++

序文:

これは、Blue Bridge シミュレーション コンペティションの最初のブログ記録です。多くの至らない点があるかもしれません。ここで、第 15 回 Blue Bridge Cup シミュレーション コンペティションのグループ B (第 2 回) の問題とコードを共有します。私は C++ を使用しました。アルゴリズムに関するいくつかの質問は、私がそれらを行っているときに混乱したため、アドバイスを得るために他の専門家とそれらのいくつかを共有しました。

目次

編集

1. 質問A

2. 質問B

3. 質問C

4. 質問D

5. テスト問題 E

6. 質問F

 7. 質問G

8. テスト問題 H 

9. テスト問題 I

10. 質問J


 

1. 質問A

問題の説明   

        Xiaolan は、各単語が同じ幅のテキスト行を画面上に配置したいと考えています。​   

        Xiaolan は、各文字の幅が 36 ピクセルの場合、1 行にちょうど 30 文字を、文字の間や前後に隙間なく配置できることを発見しました。​   

        各文字の幅が 10 ピクセルで、文字間に隙間がない場合、1 行に何文字まで配置できますか。​ 

言うことはあまりありません。これは単なる小学校の算数の問題です。36 × 30 / 10 = 108

答え: 108

二、试题B

問題の説明   

        2^2023%1000 を求めます。これは、2 の 2023 乗を 1000 で割った余りです。

%1000 には 2^2023 の下 3 桁が必要です。これは単なる穴埋め問題なので、電卓を使用して直接計算できます。

 答え: 608

3. 質問C

問題の説明   

        2 進数に変換された正の整数と 8 進数に変換された正の整数のすべての桁の合計が等しい場合、その桁の合計が等しい数値と呼ばれます。​   

        最初の数桁の合計が同じである正の整数は、1、8、9、64、... です。   

        23 桁目の和が等しい正の整数は何ですか?​ 

 ブルートフォースまたはプログラミングを使用して問題を解決できます

#include<bits/stdc++.h>

#define num first
#define y second

using namespace std;

typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

// 十进制数转换为任意n进制数
// num:十进制数,n:转换成n进制数

string Itoa(int num,int n) 
{
    string str;
    int rem;
    char ch;
    if(num == 0)
        str = "0";
    while(num > 0) 
    {
        rem = num % n;
        ch = (rem < 10) ? (rem + '0') : (rem - 10 + 'A');
        str = ch + str;
        num /= n;
     }
    return str;
}
// 计算每一位上的和
int sum(string str) 
{
    int sum = 0;
    for(int i = 0;i < str.length();i ++) 
    {
        sum += str[i] - '0';
    }
    return sum;
}
string str1;
string str2;
int main() 
{
    int cnt = 0;
    int i = 1;
    while(1) 
    {
        str1 = Itoa(i,2);
        str2 = Itoa(i,8);
        // cout<<i<<' '<<str1<<' '<<str2<<endl;
        if(sum(str1) == sum(str2)) 
        {
            cnt ++;
            cout << "数字为" << i << endl;
            cout << str1 << endl;
            cout << str2 << endl;
            cout << "cnt的值是" << cnt << endl;
        }
        if(cnt == 23) 
        {
            cout << "找到了!!!:>" << i << endl;
            cout << str1 << endl;
            cout << str2 << endl;
            break;
        }
        i ++;
    }
return 0;
}
番号は 1 です
1
1
cntの値は1です
数字は8です
1000
10
cntの値は2です
数字は9です
1001
11
cntの値は3です
その数は64です
1000000
100
cntの値は4です
その数は65です
1000001
101
cntの値は5です
その数は72です
1001000
110
cntの値は6です
その数は73です
1001001
111
cntの値は7です
その数は512です
1000000000
1000
cntの値は8です
その数は513です
1000000001
1001
cntの値は9です
その数は520です
1000001000
1010
cntの値は10です
その数は521です
1000001001
1011
cntの値は11です
その数は576です
1001000000
1100
cntの値は12です
その数は577です
1001000001
1101
cntの値は13です
その数は584です
1001001000
1110
cntの値は14です
その数は585です
1001001001
1111
cntの値は15です
番号は4096です
1000000000000
10000
cntの値は16です
番号は4097です
1000000000001
10001
cntの値は17です
番号は4104です
1000000001000
10010
cntの値は18です
番号は4105です
1000000001001
10011
cntの値は19です
番号は4160です
1000001000000
10100
cntの値は20です
番号は4161です
1000001000001
10101
cntの値は21です
番号は4168です
1000001001000
10110
cntの値は22です
番号は4169です
1000001001001
10111
cntの値は23です
見つけました!!!:>4169
1000001001001
10111

答え: 4169

四、试题D

問題の説明   

        次の数値 (6 行、各行に 6 個、合計 36 個) について、約数の数が最も大きいものはどれですか? (複数ある場合は一番早いものをご回答ください)   

        393353 901440 123481 850930 423154 240461   

        373746 232926 396677 486579 744860 468782   

        941389 777714 992588 343292 385198 876426   

        483857 241899 544851 647930 772403 109929

        882745 372491 877710 340000 659788 658675   

        296521 491295 609764 718967 842000 670302

おおよその数値のテンプレートの質問 

#include<bits/stdc++.h>

using namespace std;

const int N = 100010;

int primes[N], cnt;
bool st[N];

void init(int n)
{
    for (int i = 2; i <= n; i ++)
    {
        if (!st[i]) primes[cnt ++] = i;
        for (int j = 0; primes[j] * i <= n; j ++)
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

void divide(int x)
{
     int res = 0;
     for (int i = 0; i < cnt; i ++)
     {
        int p = primes[i];
        if (x % p == 0)
        {
            while (x % p == 0)
            {
                res ++;
                {
                    x /= p;
                }
            }
        }
     }
     cout << res << endl;
}

int main()
{
    init(N);
    int m = 30;
    while (m--)
    {
        int x;
        cin >> x;
        divide(x);
    }
    return 0;
}

答え: 901440

五、试题E

問題の説明   

        Xiaolan には 01 マトリックスがあります。彼は、最初の行と最初の列の 0 を 2 に変更するつもりです。変化のプロセスは伝染し、上下左右の隣接する4つの位置に2が入るたびに0が2になります。最終的には 2 がすべて 1 または 2 に囲まれるまでです。すみません、最終的な行列には 2 がいくつありますか?​   

        以下は Xiaolan の行列で、合計 30 行 40 列あります。 00001000100000011010101001001100000011 0101111001111101110111100000101010011111 10100 0110101010110000000101100100000101001 001 010100011 0100110010000110000000100010000101110000 1001011101101 0011110100011000000001101001101110100001 010001110111011 00 0010110000001000001010100011000010100011 000101100000000000010 0011001000001000000010011001100101000110 000110100100000101 0010001 0100010010000110100001100000110111110101 00101000000111100110010101101 | 0010110101001100000100000010000010110011 | 100 100000011000101011000000010101 1001111010010110011010101110000000101110 1000000010010011001000100110010000101 100110001010001 0000100000101111111111100 0011000100011000010111101000101110110001

 Classic BFS (breadth first search) は接続されたブロックを検索しますが、質問の意味から、接続されているブロック内のすべて 0 の 0 の数が必要であることがわかります。

#include<bits/stdc++.h>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
const int N = 45;
char g[N][N];
bool st[N][N];
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, -1, 0, 1};
int ans;

void bfs(int x, int y)
{
    queue<PII> q;
    st[x][y] = true;
    q.push({x, y});
    ans++;
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int a = dx[i] + t.x, b = dy[i] + t.y;
            if (a < 0 || a >= 30 || b < 0 || b >= 40) continue;
            if (st[a][b]) continue;
            if (g[a][b] != '0') continue;
            ans++;
            st[a][b] = true;
            q.push({a, b});
        }
    }
}
int main()
{
    for (int i = 0; i < 30; i++) cin >> g[i];
    bfs(0, 0);
    cout << ans << endl;
    return 0;
}

答え: 541 

六、试题F

問題の説明   

        正確に 6 桁の正の整数 x が与えられた場合、x を左に 1 ビット回転して出力してください。​   

        いわゆる 1 桁の左への循環シフトは、元の 100,000 桁が一の桁に変更され、元の 10,000 桁が左に移動されて 100,000 桁が十の桁になることを意味します。​   

        例: 194910 は 1 桁左にシフトされ、949101 になります。​  

        別の例: 987123 は 1 つ左にシフトされて 871239 になります。

入力フォーマット

        整数 x を含む行を入力します。入力 x に 10 進数が 6 桁正確に含まれていること、および数十万桁および数万桁の数値が 0 ではないことを確認してください。

出力フォーマット   

        出力行には、答えを表す整数が含まれます。サンプル入力 194910 サンプル出力 949101

 直接文字列、簡単なシミュレーションで十分ですが、この問題は点を取るための古典的な問題としか言いようがありません。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    string s;
    cin >> s;
    for(int i = 1; i < s.size(); i ++)
        cout << s[i];
    cout << s[1];
    
    return 0;
}

 7. 質問G

問題の説明   

        英小文字のみを含む文字列を入力してください。この文字列の最後の母音は何ですか?

        英語では、a、e、i、o、uの合計5文字が母音で、その他の文字は母音ではありません。

入力フォーマット   

        英語の小文字のみで構成され、その文字列に少なくとも 1 つの母音が含まれる文字列を含む行を入力します

出力フォーマット

        出力には、答えを表す 1 文字が含まれます。

サンプル入力

        蘭橋

サンプル出力

        ○

サンプル入力

        カップ

サンプル出力

        で

この質問は、前の質問とほぼ同じ難易度です。文字列をループし、最初の母音を後ろから前に出力する単純なシミュレーションです。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    string s;
    cin >> s;
    for(int i = s.size() - 1; i >= 0; i--)
    {
        if(s[i] == 'a' || s[i] == 'o' || s[i] == 'e' || s[i] == 'i' || s[i] == 'u')
        {
            cout << s[i] << endl;
            break;
        }
    }
    return 0;
}

8. テスト問題 H 

問題の説明   

        整数を指定すると、その整数の変換は、整数のすべての桁のゼロ以外の桁の積になります。​   

        たとえば、123456789 は 123456789=362880 に一度変換され、36288=2304 に再変換され、234=24 に再変換され、8 に再変換されます。​   

        整数が与えられた場合、変換プロセスで各整数のエクスペリエンスを 10 未満になるまで順番に出力してください。

入力フォーマット   

        整数 n を含む行を入力します。

出力フォーマット   

        複数行を出力します。各行には整数が含まれます。

サンプル入力

        123456789

サンプル出力

        362880

        2304

        24

        8

評価ユースケースの規模と規約   

        評価ケースの 50% では、1 <= n <= 10^9 (10 の 9 乗) になります。​   

        すべての評価ケースで、1 <= n <= 10^18 (10 の 18 乗)。

 単純にシミュレーションする

#include <bits/stdc++.h>

using namespace std;

int main()
{
    
    long long int n;
    cin >> n;
    long long int sum = 11; 
    while(sum >= 10)
    {
        sum = 1;
        while(n)
        {
            if((n % 10) != 0)
                sum *= n % 10;
            n /= 10;
        }
        cout << sum << " "<< endl;
        n = sum; 
    }
    return 0;
}

9. テスト問題 I

問題の説明   

        Xiaolan は n 行 m 列の正方形の図の中央に立っており、正方形の図の各正方形には正の整数がマークされています。隣接する2つのマス目(4方向に隣接するマス目)の数字の最大公約数が1より大きい場合、一方のマス目からもう一方のマス目へ移動することができ、もちろん、もう一方のマス目から戻ることもできます。​   

        シャオランが r 行、c 列から開始すると仮定します。シャオランはグリッド内で何マスまで移動できますか?

入力フォーマット   

        入力の最初の行には、グリッド チャートの行と列の数を示す、スペースで区切られた 2 つの整数 n、m が含まれています。次の n 行は、各行に m 個の正の整数が含まれており、隣接する整数の間にスペースで区切られており、グリッド チャートの行 1 から行 n まで、および各行の列 1 から列 m までの数値を表します。​   

        次の行には、Xiaolan の行番号と列番号を示す、スペースで区切られた 2 つの整数 r と c が含まれています。

出力フォーマット   

        出力行には、答えを表す整数が含まれます。

サンプル入力 

3 4

3 6 5 5

2 4 3 5

7 8 3 8

3 2

出力例 5

評価ユースケースの規模と規約   

        評価ケースの 50%、1 <= n、m <= 100 では、グリッド チャートの各数値は 10^5 (10 の 5 乗) を超えません。​   

        すべての評価ケース、1 <= n、m <= 1000 で、グリッド チャートの各数値は 10^9 (10 の 9 乗) を超えません。

BFS テンプレートの質問には、最大公約数を見つけるステップが追加されているだけです。 

#include<bits/stdc++.h>

#define x first
#define y second

using namespace std;
typedef pair<int, int> PII;
const int N = 1010;
int g[N][N];
int n, m;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, -1, 0, 1};
int ans;
bool st[N][N];

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
void bfs(int x, int y)
{
    queue<PII> q;
    st[x][y] = true;
    q.push({x, y});
    ans++;
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int a = dx[i] + t.x, b = dy[i] + t.y;
            if (a < 1 || a > n || b < 1 || b > m) continue;
            if (st[a][b]) continue;
            if (gcd(g[a][b], g[t.x][t.y]) <= 1) continue;
            st[a][b] = true;
            ans ++;
            q.push({a, b});
        }
    }
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
    cin >> g[i][j];
    int x, y;
    cin >> x >> y;
    bfs(x, y);
    cout << ans << endl;
    return 0;
}

 

10. 質問J

問題の説明   

        シーケンス a[1]、a[2]、…、a[n] と整数 k が与えられた場合、その区間内のすべての数値の合計が最大になるような、ちょうど k の長さの区間を見つけてください。​   

        つまり、1 <= p および p+k-1 <= n となるような整数 p を見つけ、a[p]+a[p+1]+...+a[p+k-1] となります。は最もおおきい 。

入力フォーマット   

        入力の最初の行には、2 つの整数 n と k が含まれています。​   

        2 行目には、指定されたシーケンスを表す、隣接する整数の間にスペースで区切られた n 個の整数が含まれています。

出力フォーマット   

        出力行には、最大間隔合計を表す整数が含まれています。合計を出力するだけでよく、計画を出力する必要はありません。サンプル入力

         6 3 2 3 9 1 9 5

サンプル出力

        19

評価ユースケースの規模と規約   

        評価ケースの 30% では、1 <= k <= n <= 30、1 <= a[i] <= 100。​   

        評価ケースの 60% では、1 <= k <= n <= 1000、1 <= a[i] <= 10000。​   

        すべての評価ケースで、1 <= k <= n <= 100000、1 <= a[i] <= 1000000。

 これは単純なスライディング ウィンドウ、プレフィックス、テンプレートの質問です。注意する必要があるのは、長く長く開くことです。そうしないと範囲を超えます。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,k;
    cin >> n >> k;
    long long int s[100000];
    for(int i = 1; i <= n; i ++)
    {
        cin >> s[i];
        s[i] += s[i - 1];
    }
    long long int m;
    
    for(int i = 1; i + k - 1 <= n; i ++)
    {
        m = max(s[i + k - 1] - s[i - 1],m);
    }
    cout << m << endl;
    
    return 0;
}

おすすめ

転載: blog.csdn.net/m0_63168877/article/details/134723259