高精度トレーニングトピック1

1:大菲波数

フィボナッチ数列は次のように定義されます: f(1)=1; f(2)=1; f(n)=f(n-1)+f(n-2) (n>=3)。つまり、1、1、2、3、5、8、13... がフィボナッチ数列です。整数 n を入力し、フィボナッチ数列の n 番目の項を見つけます。

入力形式:
まず、テスト データのグループ数を示す正の整数 T を入力し、次に T グループのテスト データを入力します。テスト データの各セットには、整数 n (1≤n≤1000) が入力されます。

出力形式:
テストのセットごとに、フィボナッチ数列の n 番目の項 f(n) を 1 行に出力します。

入力例:

2
105
4

出力サンプル:

3928413764606871165730
3

出典:
HDOJ 1715

コード長制限
16 KB
時間制限
400 ミリ秒
メモリ制限
64 MB

分析: 配列を使用して大きな整数の演算をシミュレートし、最初に質問の意味に従ってすべての結果を前処理し、最後にデータを入力してテーブルを検索します。

#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

const int N = 1010;

string f[N];

vector<int> add(vector<int>A, vector<int>B)
{
    
    
    vector<int>C;
    for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i ++ )
    {
    
    
        if(i < A.size()) t += A[i];
        if(i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main()
{
    
    
    f[1] = f[2] = "1";
    for (int i = 3; i < N; i ++ )
    {
    
    
        string s1 = f[i - 1];
        string s2 = f[i - 2];
        
        vector<int>A, B;
        for (int i = s1.size() - 1; i >= 0; i -- ) A.push_back(s1[i] - '0');
        for (int i = s2.size() - 1; i >= 0; i -- ) B.push_back(s2[i] - '0');
        
        auto C = add(A, B);
        
        string s;
        
        for (int i = C.size() - 1; i >= 0; i -- )
            s += to_string(C[i]);
        f[i] = s;
    }
    int T;
    cin >> T;
    
    while (T -- )
    {
    
    
        int x;
        cin >> x;
        cout << f[x] << endl;
    }
    
    return 0;
}

2: 大きな数の乗算

大きな正の整数と負でない整数を入力し、その積を求めます。

入力形式:
複数のテスト データ セットがあり、ファイルの最後まで処理されます。各テスト セットでは、大きな正の整数 A (桁数は 1000 を超えない) と非負の整数 B (int 範囲) を入力します。

出力形式:
テストのセットごとに、A と B の積を出力します。

入力例:

1 1
123 100
12345678910 8
123456789101234567891012345678910 7

出力サンプル:

1
12300
98765431280
864197523708641975237086419752370

出典:
ZJUTOJ 1027

注:
元の質問の B は 1 桁ですが、この質問は int の範囲の整数に変更されます。

コード長制限
16 KB
時間制限
400 ミリ秒
メモリ制限
64 MB

分析: b の範囲は int 型であり、文字列 s の各桁の範囲は 0 ~ 9 であるため、b が int 型の制限を受ける限り、s[i] は次の場合に int 型を超えると結論付けることができます。 2 ~ 9 かかります。そのため、long long 型を使用する必要があります

#include <iostream>
#include <vector>

using namespace std;

typedef long long LL;

vector<LL> mul(vector<LL>A, int b)
{
    
    
    vector<LL>C;
    for (LL i = 0, t = 0; i < A.size() || t; i ++ )
    {
    
    
        if(i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main()
{
    
    
    string s;
    int b;
    
    while (cin >> s >> b)
    {
    
    
        vector<LL>A;
        
        for (int i = s.size() - 1; i >= 0; i -- ) A.push_back(s[i] - '0');
        
        auto C = mul(A, b);
        
        for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
        cout << endl;
    }
    return 0;
}

3: 大きな数の合計

いくつかの大きな整数が与えられた場合、その合計を計算します。

入力形式:
テストデータは複数あります。テスト番号の各セットについて、最初に整数 n (n ≤ 100) を入力し、次に n 個の大きな整数を入力します (桁数は 200 を超えません)。n=0 の場合、入力が終了したことを意味します。

出力形式:
テストのセットごとに、n 個の整数の合計を出力し、各結果が個別の行を占めます。

入力例:

2
43242342342342
-1234567654321
0

出力サンプル:

42007774688021

出典:
ZJUTOJ 1214

コード長制限
16 KB
時間制限
400 ミリ秒
メモリ制限
64 MB

分析: 負の数に正の数を加算する操作は難しいため、負の数を加算する操作を数値の減算に変換できるため、この問題は高精度の加算と減算の演算を検討していると結論付けることができます。

#include <iostream>
#include <vector>
 
using namespace std;
 
vector<int> add(vector<int>&A,vector<int>&B)//加法
{
    
    
    vector<int>C;
    for(int i = 0,t = 0; i < A.size() || i < B.size() || t; i ++ )
    {
    
    
        if(i < A.size()) t += A[i];
        if(i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    while(C.back() == 0 && C.size() > 1) C.pop_back();//去掉前导的零
    return C;
}
vector<int> sub(vector<int>&A, vector<int>&B)//减法
{
    
    
    vector<int>C;
    for(int i = 0, t = 0; i < A.size(); i ++ )
    {
    
    
        t = A[i]-t;
        if(i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if(t < 0) t = 1;
        else t = 0;
    }
    while(C.back() == 0 && C.size() > 1) C.pop_back();
    return C;
}
bool cmp(vector<int>&A,vector<int>&B)//比较大小,前面大返回真,否则返回假
{
    
    
    if(A.size() != B.size()) return A.size() > B.size();
    for(int i = 0; i < A.size(); i ++ )
        if(A[i] != B[i]) return A[i] > B[i];
    return true;
}
int main()
{
    
    
    int n;
    while(cin >> n && n)
    {
    
    
        int a1 = 1,ans1 = 1;//判断符号
        vector<int>ans = {
    
    0};//初始化
        while(n -- )
        {
    
    
            string a;
            vector<int>A;
            cin >> a;
            if(a[0] == '-')
            {
    
    
                a1 = 0;
                for(int i = a.size() - 1; i > 0; i -- ) A.push_back(a[i] - '0');
            }
            else
            {
    
    
                for(int i = a.size() - 1 ; i >= 0; i -- ) A.push_back(a[i] - '0');
                a1=1;
            }
            if(cmp(ans,A))//前面大
            {
    
    
                if(ans1 && a1) ans = add(ans, A),ans1 = 1;
                else if(ans1 && !a1) ans = sub(ans, A),ans1 = 1;
                else if(!ans1 && !a1) ans = add(ans, A),ans1 = 0;
                else ans = sub(ans, A),ans1 = 0;
            }
            else
            {
    
    
                if(ans1 && a1) ans = add(ans, A),ans1 = 1;
                else if(ans1 && !a1) ans = sub(A, ans), ans1 = 0;
                else if(!ans1 && !a1) ans=add(ans, A), ans1 = 0;
                else ans = sub(A, ans),ans1 = 1;
            }
        }
        if(!ans1 && ans[0]) cout << "-";//处理符号和处理负零的情况
        for(int i = ans.size() - 1; i >= 0; i -- ) cout << ans[i];
        cout << endl;
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/qq_52331221/article/details/127787067