题解 【洛谷 P4345 [SHOI2015]超能粒子炮·改】

\(\large\mathcal{Description}\)

求:

\[\sum\limits_{i=0}^k {n \choose i} \bmod p. \]

其中 \(p = 2333.\) 数据组数为 \(10^5.\)

\(n, k\le 10^{18}\)

\(\large\mathcal{Solution}\)

\[f(n, k) = \sum\limits_{i=0}^k {n \choose i} \bmod p = \sum\limits_{i=0}^k{\lfloor \frac np\rfloor \choose \lfloor \frac ip\rfloor}{n \bmod p \choose i \bmod p} \bmod p \]

然后用类似整出分块的思想:

\[f(n, k) = {\lfloor \frac np\rfloor \choose 0}\sum\limits_{i=0}^{p-1} {n\bmod p \choose i} +{\lfloor \frac np\rfloor \choose 1}\sum\limits_{i=0}^{p-1} {n\bmod p \choose i} + \cdots + {\lfloor \frac np\rfloor \choose \lfloor \frac kp\rfloor-1}\sum\limits_{i=0}^{p-1} {n\bmod p \choose i}+{\lfloor \frac np\rfloor \choose \lfloor \frac kp\rfloor}\sum\limits_{i=0}^{k \bmod p} {n \bmod p \choose i} \]

然后前面一段:

\[{\lfloor \frac np\rfloor \choose 0}\sum\limits_{i=0}^{p-1} {n\bmod p \choose i} +{\lfloor \frac np\rfloor \choose 1}\sum\limits_{i=0}^{p-1} {n\bmod p \choose i} + \cdots + {\lfloor \frac np\rfloor \choose \lfloor \frac kp\rfloor-1}\sum\limits_{i=0}^{p-1} {n\bmod p \choose i} \]

也就是:

\[\sum\limits_{i=0}^{\lfloor \frac kp \rfloor}{\lfloor \frac np \rfloor \choose i}\times \sum\limits_{i=0}^{p-1} {n\bmod p \choose i} = f(\lfloor \frac np \rfloor, \lfloor \frac kp \rfloor) \times f(n \bmod p, p - 1) \]

后面一段就是:

\[{\lfloor \frac np\rfloor \choose \lfloor \frac kp\rfloor}\sum\limits_{i=0}^{k \bmod p} {n \bmod p \choose i} = {\lfloor \frac np\rfloor \choose \lfloor \frac kp\rfloor}\times f(n \bmod p, k\bmod p) \]

那么就有:

\[f(n, k) = f(\lfloor \frac np \rfloor, \lfloor \frac kp \rfloor) \times f(n \bmod p, p - 1) + {\lfloor \frac np\rfloor \choose \lfloor \frac kp\rfloor}\times f(n \bmod p, k\bmod p) \]

我们把 \(n<p\)\(k<p\) 时的 \(f(n, k)\) 都预处理出来,\({\lfloor \frac np\rfloor \choose \lfloor \frac kp\rfloor}\) 用卢卡斯定理处理,剩余部分递归即可。

\(\large\mathcal{Code}\)

#include <bits/stdc++.h>
#define reg register

using namespace std;

typedef long long LL;
typedef long double LDB;

const int P = 2333;

int T, f[P + 10][P + 10], C[P + 10][P + 10];

int Lucas(reg LL n, reg LL k)
{
    if (!k) return 1;
    return 1ll * Lucas(n / P, k / P) * C[n % P][k % P] % P;
}

int work(reg LL n, reg LL k)
{
    if (!k) return 1;
    if (n < P && k < P) return f[n][k];
    return (1ll * f[n % P][P - 1] * work(n / P, k / P - 1) % P + 1ll * Lucas(n / P, k / P) * f[n % P][k % P] % P) % P;
}

int main()
{
    scanf("%d", &T);
    
    for (reg int i = 0; i <= P; ++ i)
    {
        C[i][0] = 1; 
        for (reg int j = 1; j <= i; ++ j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % P;
    }
    
    f[0][0] = 1;
    for (reg int i = 0; i <= P; ++ i)
    {
        f[i][0] = 1;
        for (reg int j = 1; j <= P; ++ j) f[i][j] = (f[i][j - 1] + C[i][j]) % P;
    }
    
    while (T -- )
    {
        LL n, k;
        scanf("%lld %lld", &n, &k);
        printf("%d\n", work(n, k));
    }
    return 0;
}
posted @ 2021-08-22 15:50  DreamsChaser  阅读(82)  评论(2)    收藏  举报
Live2D