HDU3483 A Very Simple Problem (矩阵快速幂)

来源:互联网 发布:程序员才能看懂的密码 编辑:程序博客网 时间:2024/05/16 05:07

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 100003 4 1000-1 -1 -1
 

Sample Output
5050444
 

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 longstruct 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;}