數(shù)論專題:高精度計(jì)算
MT2191 整數(shù)大小比較
難度:黃金 ?? 時(shí)間限制:1秒 ?? 占用內(nèi)存:128M
題目描述
給出兩個(gè)正整數(shù),判斷它們的大小。
格式
輸入格式:兩個(gè)正整數(shù)。
輸出格式:若前者大,輸出>
;若后者大,輸出<
;若一樣大,輸出=
。樣例 1
輸入:1412894619244619891 23762842222
輸出:>
備注
保證所有數(shù)在 2 100 2^{100} 2100 以內(nèi)。
相關(guān)知識(shí)點(diǎn):
高精度計(jì)算
題解
雖然這道題是比較數(shù)字的大小,但實(shí)際上我們不用關(guān)心其數(shù)字的取值范圍(可以從字符串對(duì)象的角度出發(fā)進(jìn)行比較)。對(duì)于任意兩個(gè)正整數(shù),它們之間的大小關(guān)系可根據(jù)以下兩步進(jìn)行比較:
- 數(shù)字長(zhǎng)度。對(duì)于正整數(shù)而言,顯然長(zhǎng)度越長(zhǎng)的數(shù)更大。
- 若長(zhǎng)度相等,則從數(shù)的最高位到最低位依次比較大小,在某位上具有更大數(shù)字的數(shù)更大。
若 1、2 之后未能找到更大的數(shù),則說(shuō)明這兩個(gè)數(shù)的取值相同。
基于此,可直接寫出求解該題的完整代碼(已 AC):
/*
MT2191 整數(shù)大小比較
*/
#include<bits/stdc++.h>
using namespace std;
// 比較兩個(gè)大數(shù)的大小
int compare(string stra, string strb)
{
// 根據(jù)長(zhǎng)度判斷大小關(guān)系
int lenA = stra.length();
int lenB = strb.length();
if(lenA > lenB) return 1;
if(lenA < lenB) return -1;
// 長(zhǎng)度相等需要進(jìn)一步判斷
for(int i=0; i<lenA; i++){
if(stra[i] - strb[i] > 0) return 1;
if(stra[i] - strb[i] < 0) return -1;
}
// 或者直接比較字符串大小
// if(stra > strb) return 1;
// else if(stra < strb) return -1;
// else return
return 0;
}
// 打印結(jié)果
void printResult(int result)
{
if(result > 0) cout<<">"<<endl;
else if(result < 0) cout<<"<"<<endl;
else cout<<"="<<endl;
}
int main( )
{
// 獲取輸入
string stra, strb;
cin>>stra>>strb;
// 比較兩個(gè)大數(shù)的大小
int result = compare(stra, strb);
// 輸出比較結(jié)果
printResult(result);
return 0;
}
MT2192 A+B problem
難度:黃金 ?? 時(shí)間限制:1秒 ?? 占用內(nèi)存:128M
題目描述
計(jì)算 A + B ( 1 ≤ A , B ≤ 10 10000 ) A+B(1\le A,B\le{10}^{10000}) A+B(1≤A,B≤1010000)。
格式
輸入格式:兩行每行一個(gè)整數(shù) A , B A,B A,B。
輸出格式:一個(gè)整數(shù) A + B A+B A+B。樣例 1
輸入:
1
1輸出:
2
相關(guān)知識(shí)點(diǎn):
高精度計(jì)算
題解
這道題考察的是大數(shù)運(yùn)算(加法)。關(guān)于如何實(shí)現(xiàn)大數(shù)加法運(yùn)算的分析請(qǐng)見(jiàn)博客 【算法與數(shù)據(jù)結(jié)構(gòu)】——大數(shù)運(yùn)算 。下面給出多位數(shù)加法的執(zhí)行流程:
多位數(shù)加法的過(guò)程涉及到對(duì)各個(gè)位的加法運(yùn)算,因此在處理大數(shù)的加法運(yùn)算時(shí),通常會(huì)用一個(gè) int 型數(shù)組來(lái)存儲(chǔ)大數(shù)在各個(gè)位上的值。例如,數(shù):122333444455555666666,可通過(guò)一個(gè)足夠長(zhǎng)的數(shù)組 a r y [ ? ] ary[\ ] ary[?] ,使 a r y [ 0 ] = 1 , a r y [ 1 ] = 2 , a r y [ 3 ] = 2 , … , a r y [ 20 ] = 6 ary\left[0\right]=1,ary\left[1\right]=2,ary\left[3\right]=2,\ldots,ary\left[20\right]=6 ary[0]=1,ary[1]=2,ary[3]=2,…,ary[20]=6 進(jìn)行存儲(chǔ)。采取數(shù)位與索引大小相對(duì)應(yīng)的存儲(chǔ)方式(即數(shù)的低位對(duì)應(yīng)較小的索引,高位對(duì)應(yīng)較大的索引),是為了便于大數(shù)在執(zhí)行加法運(yùn)算時(shí)的進(jìn)位可直接在數(shù)組中向后拓展。接下來(lái),就能按照以上思路掃描數(shù)組并對(duì)各個(gè)位進(jìn)行加法運(yùn)算。最后,單獨(dú)用一層循環(huán)處理進(jìn)位即可。
下面直接給出求解本題的完整代碼(已 AC):
/*
MT2192 A+B problem
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+5;
int numa[N], numb[N];
// 計(jì)算兩個(gè)大數(shù)之和(輸入為字符串)
void getSum(string stra, string strb)
{
// 賦初值
memset(numa, 0, sizeof(numa));
memset(numb, 0, sizeof(numb));
int tmp = 0;
// 將兩個(gè)字符串保存至 int 型數(shù)組中(注意逆序)
for(int i=stra.length()-1; i>=0; i--)
numa[tmp++] = stra[i] - '0';
tmp = 0;
for(int i=strb.length()-1; i>=0; i--)
numb[tmp++] = strb[i] - '0';
// 將數(shù)組中的每個(gè)數(shù)按位進(jìn)行加法運(yùn)算
for(int i=0;i<N;i++)
numa[i] += numb[i];
// 對(duì)存放加法結(jié)果的數(shù)組執(zhí)行進(jìn)位處理
for(int i=0; i<N; i++){
numa[i+1] += numa[i] / 10;
numa[i] %= 10;
}
}
// 輸出大數(shù)加法后的結(jié)果
void printBigData()
{
// 從最高位向后掃描,直到第 1 個(gè)非 0 數(shù)字出現(xiàn)
int p = N-1;
while(numa[p] == 0) p--;
while(p >= 0) cout<<numa[p--];
cout<<"\n";
}
int main( )
{
// 獲取輸入
string stra, strb;
cin>>stra>>strb;
// 對(duì)兩個(gè)大數(shù)進(jìn)行加法運(yùn)算
getSum(stra, strb);
// 輸出和
printBigData();
return 0;
}
MT2193 A-B problem
難度:黃金 ?? 時(shí)間限制:1秒 ?? 占用內(nèi)存:128M
題目描述
計(jì)算 A ? B ( 1 ≤ B ≤ A ≤ 10 10000 ) A-B(1\le B\le A\le{10}^{10000}) A?B(1≤B≤A≤1010000)。
格式
輸入格式:兩行每行一個(gè)整數(shù) A , B A,B A,B。
輸出格式:一個(gè)整數(shù) A ? B A-B A?B。樣例 1
輸入:
2
1輸出:
1
相關(guān)知識(shí)點(diǎn):
高精度計(jì)算
題解
這道題考察的是大數(shù)運(yùn)算(減法)。關(guān)于如何實(shí)現(xiàn)大數(shù)減法運(yùn)算的分析請(qǐng)見(jiàn)博客 【算法與數(shù)據(jù)結(jié)構(gòu)】——大數(shù)運(yùn)算 。下面給出多位數(shù)減法的執(zhí)行流程:
多位數(shù)減法需要用到 int 型數(shù)組來(lái)存儲(chǔ)大數(shù)在各個(gè)位上的值,其存儲(chǔ)規(guī)則和大數(shù)加法一致(即低位對(duì)應(yīng)較小的索引,高位對(duì)應(yīng)較大的索引)。接下來(lái),只需要掃描數(shù)組,在每個(gè)位上按照以上思路進(jìn)行減法運(yùn)算即可得到大數(shù)減法的結(jié)果。
下面直接給出求解本題的完整代碼(已 AC):
/*
MT2193 A-B problem
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+5;
int numa[N], numb[N];
// 計(jì)算兩個(gè)大數(shù)之差(輸入為字符串)
void getSub(string stra, string strb)
{
// 賦初值
memset(numa, 0, sizeof(numa));
memset(numb, 0, sizeof(numb));
int tmp = 0;
// 將兩個(gè)字符串保存至 int 型數(shù)組中(注意逆序)
for(int i=stra.length()-1; i>=0; i--)
numa[tmp++] = stra[i] - '0';
tmp = 0;
for(int i=strb.length()-1; i>=0; i--)
numb[tmp++] = strb[i] - '0';
// 將數(shù)組中的每個(gè)數(shù)按位進(jìn)行減法運(yùn)算
for(int i=0;i<N;i++){
numa[i] -= numb[i];
if(numa[i] < 0){
// 借位
numa[i+1]--;
numa[i] += 10;
}
}
}
// 輸出大數(shù)減法后的結(jié)果
void printBigData()
{
// 從最高位向后掃描,直到第 1 個(gè)非 0 數(shù)字出現(xiàn)
int p = N-1;
while(numa[p] == 0) p--;
while(p > -1) cout<<numa[p--];
cout<<"\n";
}
int main( )
{
// 獲取輸入
string stra, strb;
cin>>stra>>strb;
// 對(duì)兩個(gè)大數(shù)進(jìn)行減法運(yùn)算
getSub(stra, strb);
// 輸出和
printBigData();
return 0;
}
MT2194 大斐列
難度:黃金 ?? 時(shí)間限制:1秒 ?? 占用內(nèi)存:128M
題目描述
計(jì)算斐波那契數(shù)列第 n n n 項(xiàng)。
斐波那契數(shù)列定義為: F [ 1 ] = 1 , F [ 2 ] = 1 F[1] = 1,F(xiàn)[2] = 1 F[1]=1,F[2]=1,遞推關(guān)系為: F [ N ] = F [ N ? 1 ] + F [ N ? 2 ] F[N] = F[N-1] + F[N-2] F[N]=F[N?1]+F[N?2]。即: 1 、 1 、 2 、 3 、 5 、 8 、 13 、 21 、 34 、 … … 1、1、2、3、5、8、13、21、34、…… 1、1、2、3、5、8、13、21、34、……格式
輸入格式:一個(gè)整數(shù) n n n。
輸出格式:一個(gè)整數(shù) F [ n ] F[n] F[n]。樣例 1
輸入:6
輸出:8
備注
對(duì)于 30% 的數(shù)據(jù): 3 ≤ n ≤ 20 3≤n≤20 3≤n≤20。
對(duì)于 100% 的數(shù)據(jù): 3 ≤ n ≤ 5000 3≤n≤5000 3≤n≤5000。相關(guān)知識(shí)點(diǎn):
高精度計(jì)算
題解
這道題實(shí)際上就是求斐波那契數(shù)列:即通過(guò)迭代公式 F [ N ] = F [ N ? 1 ] + F [ N ? 2 ] F[N] = F[N-1] + F[N-2] F[N]=F[N?1]+F[N?2],不斷獲取下一個(gè)值。但是斐波那契數(shù)列的增長(zhǎng)速度非常快,通過(guò)編寫 Python 代碼可知(代碼如下),斐波那契數(shù)列的第 5000 個(gè)數(shù)的長(zhǎng)度達(dá)到了 1045。因此這道題是一道妥妥的大數(shù)加法問(wèn)題。
# 求斐波那契的第 5000 項(xiàng)
ary = [1,1]
for i in range(2,5000):
ary.append(ary[i-1]+ary[i-2])
print(ary[4999])
print(len(str(ary[4999])))
所以這里依然需要用到大數(shù)加法。具體的實(shí)現(xiàn)方式和前面類似,在此就不贅述。
下面給出基于以上思路寫出的完整代碼(已 AC):
/*
MT2194 大斐列
通過(guò) python 算出最后數(shù)字(即第 5000 項(xiàng))的長(zhǎng)度為 1045
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1100;
int numa[N], numb[N], numc[N];
// 計(jì)算斐波那契數(shù)列
void getFibonacci(int n)
{
// 賦初值
memset(numa, 0, sizeof(numa));
memset(numb, 0, sizeof(numb));
memset(numc, 0, sizeof(numc));
numa[0] = numb[0] = 1;
n -= 2;
// 遞推求解斐波那契數(shù)列并統(tǒng)計(jì)前綴和
while(n--){
// 將數(shù)組中的每個(gè)數(shù)按位進(jìn)行加法運(yùn)算
for(int i=0;i<N;i++)
numc[i] = numa[i] + numb[i];
// 對(duì)存放加法結(jié)果的數(shù)組執(zhí)行進(jìn)位處理
for(int i=0; i<N; i++){
numc[i+1] += numc[i] / 10;
numc[i] %= 10;
}
// 將數(shù)組進(jìn)行前向賦值(從而實(shí)現(xiàn)遞推)
memcpy(numa, numb, sizeof(numb));
memcpy(numb, numc, sizeof(numc));
}
}
// 輸出大數(shù)加法后的結(jié)果
void printBigData()
{
// 從最高位向后掃描,直到第 1 個(gè)非 0 數(shù)字出現(xiàn)
int p = N-1;
while(numc[p] == 0) p--;
while(p > -1) cout<<numc[p--];
cout<<"\n";
}
int main( )
{
// 獲取輸入
int n;
cin>>n;
// 求出斐波那契數(shù)列
getFibonacci(n);
// 輸出指定項(xiàng)
printBigData();
return 0;
}
MT2195 升級(jí)版斐波那契數(shù)列
難度:黃金 ?? 時(shí)間限制:1秒 ?? 占用內(nèi)存:128M
題目描述
我們都知道斐波那契數(shù)列一項(xiàng)是前兩項(xiàng)的和,現(xiàn)在我們規(guī)定一個(gè)升級(jí)版斐波那契數(shù)列,其一項(xiàng)為前三項(xiàng)的和,要求算其前 n n n 項(xiàng)的和。即,定義: F [ 1 ] = 1 , F [ 2 ] = 1 , F [ 3 ] = 1 F[1] = 1,F(xiàn)[2] = 1,F(xiàn)[3] = 1 F[1]=1,F[2]=1,F[3]=1,遞推關(guān)系為: F [ N ] = F [ N ? 1 ] + F [ N ? 2 ] + F [ N ? 3 ] F[N] = F[N-1] + F[N-2] + F[N-3] F[N]=F[N?1]+F[N?2]+F[N?3]。
格式
輸入格式:一個(gè)整數(shù) n n n;
輸出格式:前 n n n 項(xiàng)的和。樣例 1
輸入:4
輸出:6
備注
其中: 4 ≤ n ≤ 1000 4\le n \le 1000 4≤n≤1000。
相關(guān)知識(shí)點(diǎn):
高精度計(jì)算
題解
這道題依然考察了大數(shù)加法,和前面一題類似,下面直接給出求解本題的完整代碼(已 AC):
/*
MT2195 升級(jí)版斐波那契數(shù)列
通過(guò) python 算出最后數(shù)字(即第 1000 項(xiàng))的長(zhǎng)度為 265,整個(gè)數(shù)列的數(shù)字之和長(zhǎng)度為 265
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 300;
int numa[N], numb[N], numc[N], numd[N], preSum[N];
// 計(jì)算斐波那契數(shù)列
void getFibonacci(int n)
{
// 賦初值
memset(numa, 0, sizeof(numa));
memset(numb, 0, sizeof(numb));
memset(numc, 0, sizeof(numc));
memset(numd, 0, sizeof(numd));
memset(preSum, 0, sizeof(preSum));
numa[0] = numb[0] = numc[0] = 1;
preSum[0] = 3;
n -= 3;
// 遞推求解斐波那契數(shù)列并統(tǒng)計(jì)前綴和
while(n--){
// 將數(shù)組中的每個(gè)數(shù)按位進(jìn)行加法運(yùn)算
for(int i=0;i<N;i++)
numd[i] = numa[i] + numb[i] + numc[i];
// 對(duì)存放加法結(jié)果的數(shù)組執(zhí)行進(jìn)位處理
for(int i=0; i<N; i++){
numd[i+1] += numd[i] / 10;
numd[i] %= 10;
}
// 將當(dāng)前項(xiàng)累加至前綴和數(shù)組中
for(int i=0;i<N;i++)
preSum[i] += numd[i];
for(int i=0; i<N; i++){
preSum[i+1] += preSum[i] / 10;
preSum[i] %= 10;
}
// 將數(shù)組進(jìn)行前向賦值
memcpy(numa, numb, sizeof(numb));
memcpy(numb, numc, sizeof(numc));
memcpy(numc, numd, sizeof(numd));
}
}
// 輸出大數(shù)加法后的結(jié)果
void printBigData()
{
// 從最高位向后掃描,直到第 1 個(gè)非 0 數(shù)字出現(xiàn)
int p = N-1;
while(preSum[p] == 0) p--;
while(p > -1) cout<<preSum[p--];
cout<<"\n";
}
int main( )
{
// 獲取輸入
int n;
cin>>n;
// 求出斐波那契數(shù)列
getFibonacci(n);
// 輸出前綴和
printBigData();
return 0;
}
MT2196 2的N次冪
難度:黃金 ?? 時(shí)間限制:1秒 ?? 占用內(nèi)存:128M
題目描述
任意給定一個(gè)正整數(shù) N ( N ≤ 100 ) N(N\le100) N(N≤100) ,計(jì)算 2 的 N N N 次方的值。
格式
輸入格式:一個(gè)正整數(shù) N N N;
輸出格式:輸出 2 N 2^N 2N 的值。樣例 1
輸入:5
輸出:32
相關(guān)知識(shí)點(diǎn):
高精度計(jì)算
題解
2 n 2^n 2n 在 n n n 取 100 時(shí),是一個(gè)長(zhǎng)度為 31 的大數(shù),因此也是一道高精度題。與前面不同的是,這道題要求的是乘冪運(yùn)算。但實(shí)際上,數(shù)的乘冪運(yùn)算就等于進(jìn)行 “冪” 次乘法運(yùn)算(疊乘),乘數(shù)為底數(shù)。所以求解該題的關(guān)鍵實(shí)際是基于乘法運(yùn)算的高精度計(jì)算問(wèn)題,關(guān)于如何實(shí)現(xiàn)大數(shù)乘法運(yùn)算的分析請(qǐng)見(jiàn)博客 【算法與數(shù)據(jù)結(jié)構(gòu)】——大數(shù)運(yùn)算 。
這里選用的數(shù)據(jù)結(jié)構(gòu)依然是 int 型數(shù)組,其存儲(chǔ)規(guī)則和大數(shù)加法一致(即低位對(duì)應(yīng)較小的索引,高位對(duì)應(yīng)較大的索引)。不過(guò)在算法一開(kāi)始,需要將該數(shù)組的最低位置為底數(shù)(即 2)。接下來(lái),定義一重循環(huán)(循環(huán)次數(shù)為 n ? 1 n-1 n?1),每遍都執(zhí)行以下兩步:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-688124.html
- 將存放大數(shù)的數(shù)組中的每一位都乘以底數(shù);
- 遍歷整個(gè)數(shù)組執(zhí)行進(jìn)位。
算法結(jié)束時(shí),即得到了大數(shù)乘冪運(yùn)算的結(jié)果。下面給出基于以上思路得到的完整代碼:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-688124.html
/*
MT2196 2的N次冪
*/
#include<bits/stdc++.h>
using namespace std;
// 題目給的數(shù)據(jù)范圍保證了結(jié)果不超過(guò) 32 位
const int N = 32;
int num[N];
// 高精度乘冪運(yùn)算
void getHighPrecision(int base, int power)
{
// 初始化存放運(yùn)算結(jié)果的數(shù)組
memset(num, 0, sizeof(num));
// 給數(shù)組賦初值
num[0] = base;
// 執(zhí)行乘冪運(yùn)算
while(--power){
// 將數(shù)組中的每個(gè)數(shù)進(jìn)行乘法運(yùn)算
for(int i=0; i<N; i++)
num[i] *= base;
// 對(duì)數(shù)組執(zhí)行進(jìn)位處理
for(int i=0; i<N; i++){
num[i+1] += num[i] / 10;
num[i] %= 10;
}
}
}
// 輸出高精度運(yùn)算后的大數(shù)
void printBigData()
{
// 從最高位向后掃描,直到第 1 個(gè)非 0 數(shù)字出現(xiàn)
int p = N-1;
while(num[p] == 0) p--;
while(p > -1) cout<<num[p--];
cout<<"\n";
}
int main( )
{
// 獲取輸入
int n;
cin>>n;
// 執(zhí)行乘冪的高精度運(yùn)算
getHighPrecision(2, n);
// 輸出
printBigData();
return 0;
}
END
到了這里,關(guān)于【馬蹄集】第二十四周——高精度計(jì)算專題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!