题目地址:
https://www.acwing.com/problem/content/1310/
佳佳碰到了一个难题,请你来帮忙解决。对于不定方程 a 1 + a 2 + ⋯ + a k − 1 + a k = g ( x ) a_1+a_2+⋯+a_{k−1}+a_k=g(x) a1+a2+⋯+ak−1+ak=g(x),其中 k ≥ 1 k≥1 k≥1且 k ∈ N + k∈N^+ k∈N+, x x x是正整数, g ( x ) = x x m o d 1000 g(x)=x^x\mod1000 g(x)=xxmod1000(即 x x x^x xx除以 1000 1000 1000的余数), x , k x,k x,k是给定的数。我们要求的是这个不定方程的正整数解组数。举例来说,当 k = 3 , x = 2 k=3,x=2 k=3,x=2时,方程的解分别为: { a 1 = 1 a 2 = 1 a 3 = 2 \left\{ \begin{array}{l} a_1=1 \\ a_2=1 \\ a_3=2 \\ \end{array} \right. ⎩ ⎨ ⎧a1=1a2=1a3=2, { a 1 = 1 a 2 = 2 a 3 = 1 \left\{ \begin{array}{l} a_1=1 \\ a_2=2 \\ a_3=1 \\ \end{array} \right. ⎩ ⎨ ⎧a1=1a2=2a3=1和 { a 1 = 2 a 2 = 1 a 3 = 1 \left\{ \begin{array}{l} a_1=2 \\ a_2=1 \\ a_3=1 \\ \end{array} \right. ⎩ ⎨ ⎧a1=2a2=1a3=1。
输入格式:
有且只有一行,为用空格隔开的两个正整数,依次为
k
,
x
k,x
k,x。
输出格式:
有且只有一行,为方程的正整数解组数。
数据范围:
1
≤
k
≤
100
1≤k≤100
1≤k≤100
1
≤
x
<
2
31
1≤x<2^{31}
1≤x<231
k
≤
g
(
x
)
k≤g(x)
k≤g(x)
先用快速幂求 n = x x m o d 1000 n=x^x\mod 1000 n=xxmod1000,接着问题转化为求 a 1 + . . . + a k = n a_1+...+a_k=n a1+...+ak=n的正整数解的个数,可以用隔板法求出答案为 ( n − 1 k − 1 ) n-1\choose k-1 (k−1n−1)。组合数有递推公式 ( n k ) = ( n − 1 k − 1 ) + ( n − 1 k ) {n\choose k}={n-1\choose k-1}+{n-1\choose k} (kn)=(k−1n−1)+(kn−1)。令 f [ n ] [ k ] = ( n k ) , k ≤ n f[n][k]={n\choose k}, k\le n f[n][k]=(kn),k≤n,已知 f [ 0 ] [ 0 ] = 1 f[0][0]=1 f[0][0]=1,一路递推即可。最终答案大概是 ( 1000 100 ) {1000\choose 100} (1001000)这个级别,需要高精度。代码如下:
#include <iostream>
using namespace std;
const int N = 150, mod = 1000;
int k, x;
int f[1000][100][N];
int qmi(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
// 高精度 a = b + c
void add(int a[N], int b[N], int c[N]) {
for (int i = 0, t = 0; i < N; ++i) {
t += b[i] + c[i];
a[i] = t % 10;
t /= 10;
}
}
int main() {
scanf("%d%d", &k, &x);
int n = qmi(x % mod, x);
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= i && j < k; ++j) {
if (!j) f[i][j][0] = 1;
else add(f[i][j], f[i - 1][j], f[i - 1][j - 1]);
}
}
// 不要打印开头0
int m = N - 1;
while (!f[n - 1][k - 1][m]) m--;
while (m >= 0) printf("%d", f[n - 1][k - 1][m--]);
puts("");
}
时间复杂度 O ( log x + k ) O(\log x+k) O(logx+k),空间 O ( 1 ) O(1) O(1)。