一、如何快速求得 a的b次方
将b分解成若干个 2^k的和且分解的个数最小———求b得二进制数
例如:求2^31: 31的二进制表示为 11111,即拆2^31次为 2的0次……的乘积
题目一:
求 A^B的最后三位表示的整数
注意: 仅保存最后三位数
从b的最低位开始依次求得b的各个二进制位,在当前二进制位位1的情况下将a累乘到ans上。在完成本位操作后对a求其平方计算下一位二进制位的权重
A^B的后三位只与A的后三位和B有关
#define _CRT_SECURE_NO_DEPRECATE
//A^B的最后三位数
#include<stdio.h>
int main()
{
int a, b;
while (scanf("%d%d", &a, &b) != EOF)
{
if (a == 0 && b == 0) break;
int ans = 1;
while (b != 0)
{
if (b % 2 == 1)
{
ans *= a;
ans %= 1000;
}
b /= 2;
a *= a; //下一位二进制的权重
a %= 1000;
}
//一边计算b的二进制,一边计算a的2^k次,并将需要的部分累乘到ans上
printf("%d\n", ans);
}
return 0;
}
题目二:
只有等比数列和等差数列。。。等差数列直接用公式求。。。等比数列用二分求幂法。。。// 不要忘了%200907。。。注意整数类型。。。
#define _CRT_SECURE_NO_DEPRECATE
//等差数列或者等比数列的第k项
#include<stdio.h>
#include<algorithm>
using namespace std;
#define M 200907
long long fun(long long a, long long d ,long long k)
{
--k;
long long ans = a; //等比初项
while (k != 0)
{
if (k % 2 == 1)
{
ans *= d;
ans %= M;
}
k /= 2;
d *= d;
d %= M;
}
return ans;
}
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
while (n--)
{
int k;
long long res = 0;
long long a, b, c;
scanf("%lld%lld%lld%d", &a, &b, &c,&k);
if (b*2 == a+c)
{
long long dis = b - a;
res = (a%M) + ((k - 1) % M)*((dis%M) % M) % M;
}
else {
long long dis = b / a;
res = fun(a,dis,k);
}
printf("%lld\n", res);
}
}
return 0;
}
二、高精度整数
有一些整数可能数值肥肠巨大,以至于我们不能使用任何内置整数类型来保存它的值
高精度整数的保存形式:
struct bigInteger{
int digit[1000]; //按照四位数一个单元来保存数字
int size; //第一个我们还没使用过的数组单元
}
题目一:
a+b
a和b的位数不超过1000位—-采用结构体来完成对其的保存
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
struct bigInteger {
int digit[1000]; //按照四位数一个单元来保存数字
int size;
void init()
{
for (int i = 0; i < 1000; i++) digit[i] = 0;
size = 0;
}
void set(char str[]) //从字符串中提取整数
{
init();
int L = strlen(str);
for (int i = L - 1, j = 0, t = 0, c = 1; i >= 0; i--)
{
//从最后一个字符开始倒序遍历字符串,j控制每4个字符转换为一个数字
//t临时保存字符转换为数字的中间值,c表示当前位的权重
t += (str[i] - '0')*c;
j++;
c *= 10;
if (j == 4 || i == 0)
{
digit[size++] = t; //将这四个字符代表的四位数存入数组,size移动到下一个数组单元
j = 0; //计算下4个字符
t = 0;
c = 1;
}
}
}
void output() //将该高精度整数输出
{
for (int i = size - 1; i >= 0; i--)
{
if (i != size - 1)
printf("%04d", digit[i]); //当前数字不是最高位数字,输出前导零
else
printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator + (const bigInteger &A) const {
bigInteger ret;
ret.init();
int carray = 0;
for (int i = 0; i < A.size || i < size; i++)
{
int tmp = A.digit[i] + digit[i] + carray;
carray = tmp / 10000;
tmp %= 10000;
ret.digit[ret.size++] = tmp;
}
if (carray != 0)
{
ret.digit[ret.size++] = carray;
}
return ret;
}
}a,b,c;
char str1[1002], str2[1002];
int main()
{
while (scanf("%s%s", str1, str2) != EOF)
{
a.set(str1); //从字符串中提取整数
b.set(str2);
c = a + b;
c.output();
}
return 0;
}
题目二:n的阶乘
(1000!)非常大,依旧需要利用高精度整数来完成计算
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
struct bigInteger {
int digit[1000];
int size;
void init()
{
for (int i = 0; i < 1000; i++) digit[i] = 0;
size = 0;
}
void set(int x) { //对小整数4位为一个单位分解一次放入digit当中
init();
do {
digit[size++] = x % 1000;
x /= 1000;
} while (x != 0);
}
void output() {
for (int i = size - 1; i >= 0; i--)
{
if (i != size - 1)
printf("%04d", digit[i]);
else
printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator * (int x)const {
bigInteger ret;
ret.init();
int carray = 0;
for (int i = 0; i < size; i++)
{
int tmp = x * digit[i] + carray;
carray = tmp / 10000;
tmp %= 10000;
ret.digit[ret.size++] = tmp;
}
if (carray != 0)
{
ret.digit[ret.size++] = carray;
}
return ret;
}
}a;
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
a.init();
a.set(1);
for (int i = 1; i <= n; i++)
a = a * i;
a.output();
}
return 0;
}