Given N and K, you have to find
(1K + 2K + 3K + ... + NK) % 232
Input starts with an integer T (≤ 200), denoting the number of test cases.
Each case contains two integers N (1 ≤ N ≤ 1015) and K (0 ≤ K ≤ 50) in a single line.
For each case, print the case number and the result.
3
3 1
4 2
3 3
Case 1: 6
Case 2: 30
Case 3: 36
没什么好说的,普通的快速幂肯定会超时,所以这里就用到矩阵快速幂。这个问题最重要的是推出状态转移方程。
把操作矩阵D表示出来即可
#include<iostream>
#include<stdio.h>
#include<string>
#include<math.h>
#include<vector>
#include<string.h>
#include<iterator>
using namespace std;
typedef unsigned long long ll;
ll n,k;
const ll mod = ((ll)1<<32);
struct Matrix{
ll a[55][55];
void init(){
for(int i = 0; i< k+ 2 ;i++){
for(int j = 0; j< k + 2; j ++){
if(i==j)
a[i][j] = 1;
else
a[i][j] = 0;
}
}
}
void init2(){
for(int i = 0; i< k+ 2 ;i++){
for(int j = 0; j< k + 2; j ++){
a[i][j] = 0;
}
}
}
}A;//矩阵表示
void init1(){
int i,j;
A.a[0][0] = 1;
for(i=1;i<k+2;i++){
for(j=0;j<i;j++){
A.a[i][j] = 0;
}
}
for(i=0;i<k+2;i++)
A.a[i][k+1] = 1;
for(i=k;i>0;i--){
for(j=k;j>=0;j--){
A.a[i][j] = A.a[i+1][j] + A.a[i+1][j+1];
}
}
for(j=1;j<k+2;j++)
A.a[0][j] = A.a[1][j];
/*for(i=0;i<k+2;i++){
for(j=0;j<k+2;j++){
cout<<A.a[i][j]<<" ";
}
cout<<endl;
}*/
}
Matrix multiply(Matrix x,Matrix y){
Matrix ans;
ans.init2();
for(int i = 0 ;i < k+2; i++){
for(int p = 0; p < k+2 ;p++)
for(int j = 0; j < k+2; j++){//改变p和j的顺序能有效的改进复杂度
ans.a[i][j]=(ans.a[i][j]+(x.a[i][p]*y.a[p][j])%mod)%mod;//注意取模的地方
}
}
return ans;
}//矩阵的乘法
Matrix Matrix_pow(Matrix ma,ll n){
Matrix ans;
ans.init();
while(n){
if(n%2==1)
ans = multiply(ans,ma);
ma = multiply(ma,ma);
n>>=1;
}
return ans;
}//矩阵的快速幂
int main()
{
int t;
int i,j;
ll result;
int a,b;
scanf("%d",&t);
for(j=1;j<=t;j++){
scanf("%lld %lld",&n,&k);
init1();
result = 0;
Matrix x = Matrix_pow(A,n-1);
/*for(a = 0 ;a<k+2;a++){
for(b=0;b<k+2;b++){
cout<<x.a[a][b]<<" ";
}
cout<<endl;
}*/
for(i=0;i<k+2;i++){
result = (result + x.a[0][i]%mod)%mod;
}
cout<<"Case "<<j<<": "<<result<<endl;
}
return 0;
}