版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/84480922
题目链接:哆啦A梦传送门
题意:自己看。
参考博客:神犇
题解:分块矩阵:分块矩阵可以构造求和。
例如:我们可以这样构造,
还需注意一点的是:算完S(k+1),取出右上角矩阵分块后,还需减掉单位矩阵E。
代码不是我写的,我就按自己习惯改了下变量,主要是博主写的太溜了,不搬都对不起他:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
LL mod;
int n,k;
struct mat{
LL a[70][70];
mat(){ memset(a,0,sizeof(a));}
mat operator * (const mat y)
{
mat ans;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
ans.a[i][j]=(ans.a[i][j]+a[i][k]*y.a[k][j])%mod;
return ans;
}
mat operator + (const mat y)
{
mat ans;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans.a[i][j]=(ans.a[i][j]+y.a[i][j])%mod;
return ans;
}
};
mat mat_pow(mat x,int k)
{
mat ans;
for(int i=1;i<=n;i++) ans.a[i][i]=1;
while(k)
{
if(k&1) ans=ans*x;
x=x*x;
k>>=1;
}
return ans;
}
int main()
{
while(~scanf("%d%d%lld",&n,&k,&mod))
{
mat p;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++){
scanf("%lld",&p.a[i][j]); ///左上角矩阵
p.a[i][j]%mod;
}
p.a[i+n][i+n]=1; ///构造右下角单位阵
p.a[i][i+n]=1;///构造左上角单位阵
}
n<<=1;
mat item=mat_pow(p,k+1);
n>>=1;
mat ans;
for(int i=1;i<=n;i++)
for(int j=n+1;j<=n*2;j++) ///把右上角的矩阵分块取出
ans.a[i][j-n]=item.a[i][j];
for(int i=1;i<=n;i++){
ans.a[i][i]--; ///减去单位矩阵
if(ans.a[i][i]<0) ans.a[i][i]+=mod;
}
for(int i=1;i<=n;i++) ///输出
{
for(int j=1;j<=n;j++)
printf("%lld ",ans.a[i][j]);
puts("");
}
}
return 0;
}
我的标签:做个有情怀的程序员。