lightoj-1282 快速幂+数学

VJ题目链接:https://vjudge.net/problem/LightOJ-1282

题目大意

给你两个数 ( n , k ) (n,k) (n,k), ( 2 ≤ n ≤ 2 31 ) \left( 2\leq n\leq 2^{31}\right) (2n231), ( 1 ≤ k ≤ 1 0 7 ) \left( 1\leq k\leq 10^{7}\right) (1k107)
让你求 n k n^{k} nk的前三位数和后三位数

思路

n k n^{k} nk的后三位数很好求,直接快速幂然后对1000取模即可,
它的前三位数就要算一下
首先用科学计数法表示数,如 123465789 = 1.23456789 ⋅ 1 0 8 123465789=1.23456789\cdot 10^{8} 123465789=1.23456789108
那么 n k = x ⋅ 1 0 l e n − 1 n^{k}=x\cdot 10^{len-1} nk=x10len1,其中 l e n len len n k n^{k} nk的位数,即 l e n = lg ⁡ ( n k ) len=\lg \left( n^{k}\right) len=lg(nk)
∴ l e n = k ⋅ lg ⁡ ( n ) \therefore len=k\cdot \lg \left( n\right) len=klg(n)
对这个式子 n k = x ⋅ 1 0 l e n − 1 n^{k}=x\cdot 10^{len-1} nk=x10len1两边取对数得到
k ⋅ lg ⁡ ( n ) = lg ⁡ ( x ) + ( l e n + 1 ) k\cdot \lg \left( n\right)=\lg \left(x\right)+\left( len+1\right) klg(n)=lg(x)+(len+1)
这样就可以解出x
n k n^{k} nk的前三位就是x的前三位

AC代码

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long ll;
#define wfor(i,j,k) for(i=j;i<k;++i)
#define mfor(i,j,k) for(i=j;i>=k;--i)
// void read(int &x) {
//  char ch = getchar(); x = 0;
//  for (; ch < '0' || ch > '9'; ch = getchar());
//  for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
// }
ll ksm(ll a, ll b, ll mod)
{
    ll ans = 1;
    while (b)
    {
        if (b & 1)
            ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
int main()
{
    //std::ios::sync_with_stdio(false);
#ifdef test
    freopen("F:\\Desktop\\question\\in.txt", "r", stdin);
#endif
#ifdef ubuntu
    freopen("/home/time/debug/debug/in", "r", stdin);
    freopen("/home/time/debug/debug/out", "w", stdout);
#endif
    int t;
    scanf("%d", &t);
    int casecnt = 0;
    while (t--)
    {
        casecnt++;
        int n, k;
        scanf("%d %d", &n, &k);
        int anslast = ksm(n, k, 1000);
        int len = k * log10(n * 1.0);
        double x = pow(10, k * log10(n * 1.0) - len + 1);
        while (x < 100)
            x *= 10;
        int ans = floor(x);
        printf("Case %d: %03d %03d\n", casecnt, ans, anslast);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值