A Very Simple Problem
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1112 Accepted Submission(s): 549
Problem Description
This is a very simple problem. Given three integers N, x, and M, your task is to calculate out the following value:
Input
There are several test cases. For each case, there is a line with three integers N, x, and M, where 1 ≤ N, M ≤ 2*109, and 1 ≤ x ≤ 50.
The input ends up with three negative numbers, which should not be processed as a case.
Output
For each test case, print a line with an integer indicating the result.
Sample Input
100 1 10000 3 4 1000 -1 -1 -1
Sample Output
5050 444
Source
2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3483
题意:就是让求 segma(k^x*x^k)(1<=k<=n)的和。
思路:明显的要用矩阵快速幂求解,假设Sn = segma(k^x * x^k)(1<=k<=n),则Sn = Sn-1 + (n^x * x^n),令Xn-1 = {Sn-1,(n-1)^x........1}T,其中除了第一项外其余项都要*X^n,然后可以求出系数矩阵A
然后就可以对ori.a数组进行初始化操作,注意初始化的时候除了ori.a[0][0]外,其余都要*x,原因上面已经说过就不再啰嗦。当n=2时,得出的才是x1,所以Xn = A*Xn-1,求得的为Sn-1,Xn+1求出的才是Sn,所以就是Xn+1 = A^n * X1。
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct Matrix{
ll a[55][55];
}ori,res;
ll n,m,x,c[55][55];
void Init(){
memset(c,0,sizeof(c));
c[0][0] = 1;
for(int i = 1; i <= x; i ++){
for(int j = 0; j <= i; j ++){
if(j == 0 || j == i) c[i][j] = 1;
else c[i][j] = c[i-1][j-1] + c[i-1][j];
}
}
memset(ori.a,0,sizeof(ori.a));
ori.a[0][0] = 1;
for(int i = 1; i <= x+1; i ++){
ori.a[0][i] = c[x][i-1] * x % m;
}
for(int i = 1; i <= x+1; i ++){
for(int j = i,k = 0; j <= x+1; j ++,k ++){
ori.a[i][j] = c[x-i+1][k] * x % m;
}
}
memset(res.a,0,sizeof(res.a));
for(int i = 0; i <= x+1; i ++)
res.a[i][i] = 1;
}
Matrix multiply(Matrix b, Matrix d){
Matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int i = 0; i <= x+1; i ++){
for(int j = 0; j <= x+1; j ++){
for(int k = 0; k <= x+1; k ++){
temp.a[i][j] = (temp.a[i][j] + b.a[i][k] * d.a[k][j]) % m;
}
}
}
return temp;
}
void calcu(int n){
while(n){
if(n & 1) res = multiply(res,ori);
n >>= 1;
ori = multiply(ori,ori);
}
printf("%lld\n",(res.a[0][x+1] + m) % m);
}
int main(){
while(~scanf("%lld%lld%lld",&n,&x,&m)){
if(n < 0 && m < 0 && x < 0) break;
Init();
calcu(n);
}
return 0;
}