数学问题---四

一、如何快速求得 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值