hdu 6217 BBP Formula

orz看了题解才会
https://www.cnblogs.com/LzyRapx/p/7802790.html
用我的语言复述一下

把这几项拆开来看。以第一项为例
∑ k = 0 ∞ 4 1 6 k ( 8 k + 1 ) = ∑ k = 0 n − 1 4 1 6 k ( 8 k + 1 ) + ∑ k = n ∞ 4 1 6 k ( 8 k + 1 ) \sum_{k = 0}^{\infty} \frac{4}{16^k(8k+1)} = \sum_{k=0}^{n-1} \frac{4}{16^k(8k+1)} + \sum_{k=n}^{\infty} \frac{4}{16^k(8k+1)} k=016k(8k+1)4=k=0n116k(8k+1)4+k=n16k(8k+1)4

注意到后面那项减小很快,所以后面那项随便算一些项误差就几乎为0了。

下面只看前面那项
∑ k = 0 n − 1 4 1 6 k ( 8 k + 1 ) \sum_{k=0}^{n-1} \frac{4}{16^k(8k+1)} k=0n116k(8k+1)4
我们要算第n位小数。所以乘上 1 6 n − 1 16^{n-1} 16n1之后,变成了求第一位数。

∑ k = 0 n − 1 4 ∗ 1 6 n − 1 − k 8 k + 1 \sum_{k=0}^{n-1} \frac{4 * 16^{n-1-k}}{8k+1} k=0n18k+1416n1k
显然整数部分是没用的。所以其实有意义的只有除法的余数。所以上式等价于
∑ k = 0 n − 1 4 ∗ 1 6 n − 1 − k m o d ( 8 k + 1 ) 8 k + 1 \sum_{k=0}^{n-1} \frac{4 * 16^{n-1-k} mod (8k+1)}{8k+1} k=0n18k+1416n1kmod(8k+1)
就可以用快速幂了。

其他项同理。

S ( x ) = ∑ k = 0 n − 1 1 6 n − 1 − k m o d ( 8 k + x ) 8 k + x + ∑ k = n ∞ 1 1 6 k ( 8 k + x ) S(x) = \sum_{k=0}^{n-1} \frac{16^{n-1-k} mod (8k+x)}{8k+x} + \sum_{k=n}^{\infty} \frac{1}{16^k(8k+x)} S(x)=k=0n18k+x16n1kmod(8k+x)+k=n16k(8k+x)1
所以最终答案就是
4 S ( 1 ) − 2 S ( 4 ) − S ( 5 ) − S ( 6 ) 4S(1) - 2S(4) - S(5) - S(6) 4S(1)2S(4)S(5)S(6)
的第一位小数。

代码:

#include 
#include 

using namespace std;

typedef long long LL;

template <typename T>
int mpow(int base, T ex, int p) {
    int ans = 1;
    for (; ex; ex >>= 1, base = (LL)base * base % p)
        if (ex & 1)
            ans = (LL)ans * base % p;
    return ans;
}

int n;
double S(int x) {
    double ans = 0;
    for (int k = n; k < n + 22; ++k) {
        ans = fmod(ans + 1 / (pow(16, k) * (8 * k + x)), 1);
    }
    for (int k = 0; k < n; ++k) {
        ans = fmod(ans + (double)mpow(16, n - 1 - k, 8 * k + x) / (8 * k + x), 1);
    }
    return ans;
}

char hex(int x) {
    if (0 <= x && x <= 9) {
        return x + '0';
    } else {
        return x - 10 + 'A';
    }
}

int main() {
    int T;

    scanf("%d", &T);
    for (int Ti = 1; Ti <= T; ++Ti) {
        scanf("%d", &n);
        printf("Case #%d: %d %c\n", Ti, n, hex(fmod(fmod(4 * S(1) - 2 * S(4) - S(5) - S(6), 1) + 1, 1) * 16));
    }
    return 0;
}

你可能感兴趣的:(数学)