标签:
题意:求式子(1^K + 2^K + 3^K + … + N^K) % 2^32,给出N和K,1<=n <=10^15, 1 <= k <= 50。
题解:可以看到N很大,数组肯定开不下,只能从K入手,让f(x + 1) = f(x) + (x + 1) ^k,x从1开始到n-1,然后看到(x + 1)^k是一个二项展开式,针对这个展开式构造一个包含C(n, m)的矩阵。
| f(x) x^k x^(k - 1) x^(k - 2) 1 |
| 1 0 0 0 … 0 |
| C(k,0) C(k,0) 0 0 …0 |
| C(k,1) C(k,1) C(k-1,0) 0 0 … 0 |
| C(k,2) C(k,2) C(k-1,1) C(k-2,0) 0 0 … 0 |
| … |
| C(k,k) C(k,k) C(k-1,k-1) C(k-2,k-2) … 1 |
#include <stdio.h>
#include <string.h>
#include <math.h>
const long long MOD = pow(2, 32);
const int N = 55;
struct Mat {
long long g[N][N];
}ori, res;
long long n, k, c[N][N];
void init() {
c[0][0] = 1;
for (int i = 1; i <= 50; i++) {
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; j++)
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
}
}
Mat multiply(Mat x, Mat y) {
Mat temp;
for (int i = 0; i < k + 2; i++)
for (int j = 0; j < k + 2; j++) {
temp.g[i][j] = 0;
for (int l = 0; l < k + 2; l++)
temp.g[i][j] = (temp.g[i][j] + (x.g[i][l] * y.g[l][j]) % MOD) % MOD;
}
return temp;
}
void calc(long long n) {
while (n) {
if (n & 1)
ori = multiply(ori, res);
n >>= 1;
res = multiply(res, res);
}
}
int main() {
init();
int t, cas = 1;
scanf("%d", &t);
while (t--) {
scanf("%lld%lld", &n, &k);
memset(res.g, 0, sizeof(res.g));
memset(ori.g, 0, sizeof(ori.g));
res.g[0][0] = 1;
for (int i = 0; i < k + 1; i++)
res.g[i + 1][0] = c[k][i];
for (int i = 1; i < k + 2; i++)
for (int j = i, l = 0; j < k + 2; j++, l++)
res.g[j][i] = c[k - i + 1][l];
for (int i = 0; i < k + 2; i++)
ori.g[0][i] = 1;
calc(n - 1);
printf("Case %d: %lld\n", cas++, ori.g[0][0]);
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/hyczms/article/details/46336593