UVa 11029 - Leading and Trailing 数学题(求n^k的前N位和后N位)

/**
* 题意求n^k的前三位和后三位:
*
* 一开始就是把n变成小数,循环运算,然后再乘1000取前三位,结果TLE。。。
* 总是忘了用log神器。。。
*
* 首先,后三位好求。 快速幂取模就行。或者循环取模应该也不会超市。
*
* 再者,前三位:
*      这里就要用到log神器了。。。
*    设 n^k = A   两边取对数有: lgA = k * lgn;
*    则 原来的n^k 就可以表示成 10^(lgA) 即 10^(k*lgn) 亦即 pow(10, k*lgn);
*    当然这样还是不行的。  再看看 k*lgn
*    如果把k*lgn 分解成整数部分z和小数部分d的话,也就是 k*lgn = z + d;
*    原来的pow(10, k*lgn)就变成了pow(10, z + d);
*    又因为,pow(10, z) (z为整数)是不影响n^k的具体数字的,也就是说pow(10, z)的值是1000..(z个零)
*    所以我只需要用到小数部分d,这样pow(10, d)就不会溢出了,但是要如何得到前三位呢?
*    方法 pow(10, 2 + d) 其实就是乘100, 因为pow(10, d)得到的是个大于1小于10的整数。
*    最后就还剩如何表示d了。  方法: d = fmod(k * log10((double)n), 1)
*/


#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <queue>
#include <map>
#include <algorithm>
#define INF 0x7fffffff
#define MODX 1000
using namespace std;

int qmod(int p, int n) {
    int ans = 1;
    while(n > 0) {
        if(n & 1) {
            ans = (ans % MODX) * (p % MODX) % MODX;
        }
        p = (p % MODX) * (p % MODX) % MODX;
        n >>= 1;
    }

    return ans;
}

int main()
{
    int t, num;
    int head, latter, times;
    scanf("%d", &t);
    while(t --) {
        scanf("%d%d", &num, ×);
        /* the last 3 digits. */
        latter = qmod(num, times);

        /* the first 3 digits. */
        head = (int)pow(10, 2 + fmod(times * log10((double)num), 1));

        printf("%d...%03d\n", head, latter);
    }
    return 0;
}

你可能感兴趣的:(UVa 11029 - Leading and Trailing 数学题(求n^k的前N位和后N位))