这道题,出现了些本不该犯的错误,以致在这道题上面,徘徊了整一天吧。虽然今天近乎满课。
先放代码:
//AC
//HDU 6395
#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
int a,b,c,d,p,n;
const int mod = 1e9+7;
struct Matrix
{
long long num[3][3];
Matrix()
{
memset(num,0,sizeof(num));
}
};
typedef struct Matrix mat;
void print(mat a)
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
cout<<a.num[i][j]<<" ";
cout<<endl;
}
}
mat Matrixpow(mat a, mat b)
{
mat res;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
res.num[i][j] += ((a.num[i][k] * b.num[k][j]) % mod);
}
}
}
return res; //害我好惨
}
mat Quick(mat di , int zhi)
{
mat res = di;
mat ans;
for(int i=0;i<3;i++)
{
// for(int j=0;j<3;j++)
// {
// ans.num[i][j] = 0;
// }
ans.num[i][i]=1;//注意初始化成单位矩阵,只有对角线为1
}
while(zhi)
{
if(zhi & 1)
{
ans = Matrixpow(ans, res);
}
res = Matrixpow(res,res);
zhi = zhi>>1;
}
// print(ans);
return ans;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>a>>b>>c>>d>>p>>n;
if(n==1)
{
cout<<a<<endl;
continue;
}
if(n==2)
{
cout<<b<<endl;
continue;
}
mat con;
con.num[0][0]=d;
con.num[0][1]=c;
con.num[1][0]=1;
con.num[2][2]=1;
mat ans;
for(int i=0;i<3;i++)
ans.num[i][i]=1;
for(int i = 3;i<=n;)
{
int curp=i;
int endp;
if(p/i)
{
endp= min(p/(p/i) , n); //这是个WA点啊,此处错辽。。。
}
else
{
endp = n;
}
// cout<<"curp:"<<curp<<" endp: "<<endp<<endl;
int zhi = endp - curp + 1;
con.num[0][2]=p/i;
mat t = Quick(con,zhi);
// cout<<"ans:"<<endl;
// print(t);
ans = Matrixpow(t,ans);
// print(ans);
// print(ans);
i=endp + 1;
}
// ans
long long ansnum = 0;
ansnum=(ans.num[0][0]*b)%mod+(ans.num[0][1]*a)%mod+(ans.num[0][2])%mod;
ansnum = ansnum % mod;
cout<<ansnum<<endl;
}
}
这道题,考察了矩阵相乘,矩阵快速幂,整数分块。
矩阵相乘,自己错在了两个地方:
一个是,矩阵初始化时,不由分说的,要么初始化全部元素成1,要么初始化全部元素成0。这种想法很危险。在线性代数里,我难道没有学过单位矩阵 I 嘛?难受。
矩阵相乘时,自己单独写出来一个函数,但是这个函数自己却没有写返回值??所以今天找了一个小时,我说怎么一矩阵相乘,返回值就是很大很大的数。难受。
矩阵快速幂:
跟快速幂的感觉差不多,把指数看成二进制。整数的时候,那个1这里应该就是单位矩阵。同时,注意一下矩阵相乘的左右位置。
整数分块:
这里WA了两次,然后找了个大佬AC的程序,开始对拍。发现自己p>n的时候,出现了问题。
给出例子:4 3 1 2 4 3.
正确答案应该是11。
也就是整数分块,n不一定卡在分界点啊。当时写的时候,没有仔细地测一下,思维也不严谨。吸取教训。