祭奠下我又一个wa了20+次的题,(都是泪啊。~~),这个题的也其实就是一个矩阵快速幂,但是写的时候有一些小坑,比如数据都要取long long 的,改了后我还是 wa,其实是结构体的里的矩阵也要ll,然而这个 一直忘记改了,就这样一直wa。。。。。。。。。。。还有就是在重载 * 运算的时候的行列大小要搞对,m*n 的与n*p的相乘,可以得到m*p然后中间的变量k的值就是最大到第一个矩阵的列数或者第二个矩阵的行数。
最后还有一个地方有小坑,就是当p=q=0的时候,不要急着就退出了,因为这个时候a=b=0,那么输出可以是0,不要退出(虽然题目也告诉我要退出,但是就改了这么一个地方测试着交了一发,就会wa掉,= =!)(题目的意思应该是只包含两个0的,如果是0 0 k 这样三个的就继续正常进行咯?!= =?,感觉以后还是好好读题把。)
下面包含着两种写法(另外一个是递归的)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
ll p,q,n;
struct Mat {
ll mat[5][5];
int r,c;
//Mat(int _r,int _c):r(_r),c(_c) {};
};
Mat operator * (Mat a, Mat b) {
Mat m;
memset(m.mat, 0, sizeof(m.mat));
m.r=a.r;
m.c=b.c;
int i, j, k;
for(i = 0; i < m.r; ++i) {
// if(a.mat[i][k] <= 0) continue; //***
for(j = 0; j < m.c; ++j) {
// if(b.mat[k][j] <= 0) continue; //***
for(k=0;k<a.c;++k)
m.mat[i][j] = m.mat[i][j]+a.mat[i][k] * b.mat[k][j];
}
}
return m;
}
Mat operator ^ (Mat a, ll k) {
Mat m;
m.r=a.r;
m.c=a.c;
int i,j;
for(i = 0; i < m.r; ++i)
for(j = 0; j < m.c; ++j)
m.mat[i][j] = (i == j);
for(; k; k >>= 1) {
if(k&1) m = m*a;
a = a*a;
}
return m;
}
Mat multiply(Mat a,Mat b)
{
Mat m;
m.r=a.r;m.c=a.c;
for(int i=0;i<m.r;++i){
for(int j=0;j<m.c;++j){
m.mat[i][j]=0;
for(int k=0;k<a.c;++k)
m.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
}
}
return m;
}
Mat matrix_pow(Mat m,int n)
{
if(n==0){
m.mat[0][0]=m.mat[1][1]=1;
m.mat[0][1]=m.mat[1][0]=0;
return m;
}
if(n==1)
return m;
Mat res=matrix_pow(m,n/2);
res=multiply(res,res);
if(n&1)
res=multiply(res,m);
return res;
}
int main()
{
while(scanf("%lld%lld%lld",&p,&q,&n)==3)
{
if(n==0)
{
printf("2\n");
continue;
}
if(n==1)
{
printf("%d\n",p);
continue;
}
Mat a;
a.mat[0][0]=p;
a.mat[0][1]=-q;
a.mat[1][0]=1;
a.mat[1][1]=0;
a.r=2;a.c=2;
Mat b;
b.mat[0][0]=p*p-2*q;
b.mat[1][0]=p;
b.r=2;b.c=1;
ll k=n-2;
Mat tmp=a^k;
tmp=tmp*b;
ll sum=tmp.mat[0][0];
cout<<sum<<endl;
}
return 0;
}