大多数都是递推关系,其中很大的一个应用就是fibonacci数列
难点其实在于构造适当的矩阵,以下是一些应用
(1)线性齐次及非齐次递推式的快速求项,求和
(2)计算几何中点和图形的坐标(旋转,平移,伸压)变换
(3)不涉及插入、删除的点变换,区间变换和查询
(4)图论中的路径数问题
(5)dp的优化之线性递推方程优化(本质和(1)是一样的)
(6)dp及AC自动机之状态优化(将状态看作图上的点,转移看作边,本质和(1)是一样的)
【一本通的题】
1641: 【例 1】矩阵 A×B
very very 简单的一道题
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
int n,m,p;
LL a[110][110],b[110][110],c[110][110];
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) scanf("%lld",&a[i][j]);
scanf("%d",&p);
for(int i=1;i<=m;i++)
for(int j=1;j<=p;j++) scanf("%lld",&b[i][j]);
for(int i=1;i<=n;i++){ //最外面的两次是最后结果矩阵的大小
for(int j=1;j<=p;j++){
for(int z=1;z<=m;z++){
c[i][j]+=a[i][z]*b[z][j];
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=p;j++) printf("%lld ",c[i][j]);
printf("\n");
}
return 0;
}
1642: 【例 2】Fibonacci 第 n 项
这个就是模板题了
初始矩阵是 1 0
转移矩阵是1 1
1 0
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
//这个是模板
//斐波那契数列取模
/*
(1)
1 0 * 1 1 = 1 1
1 0
(2)
1 1 * 1 1 = 2 1
1 0
(3)
2 1 * 1 1 = 3 2
1 0
所以第n项就是1 0 * (1,1)^n
(1,0)
用快速幂优化就是矩阵快速幂了
*/
LL n,mod;
LL a[3][3],b[3][3],ans[3][3],c[3][3];
void add(LL &x,LL y){
x=x+y;
x-=(x>=mod)?mod:0;
return;
}
// memmove用于拷贝字节,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。
//但是当目标区域与源区域没有重叠则和memcpy函数功能相同。
int main(){
scanf("%lld %lld",&n,&mod);
n-=1;
a[1][1]=a[1][2]=a[2][1]=1;a[2][2]=0;
ans[1][1]=ans[2][2]=1; //ans是单位矩阵
ans[2][1]=ans[1][2]=0;
while(n){
if(n&1){ //快速幂
memset(c,0,sizeof(c));
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++) add(c[i][j],ans[i][k]*a[k][j]%mod);
}
}
memmove(ans,c,sizeof(ans)); //这个函数是实现字节的拷贝 把c放在ans里面
}
memset(c,0,sizeof(c));
//对a进行倍乘
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++) add(c[i][j],a[i][k]*a[k][j]%mod);
}
memmove(a,c,sizeof(a));
n>>=1;
}
//这个快速幂主要目的是求出ans数组,然后最后直接与b相乘
b[1][1]=1;b[1][2]=0;
memset(c,0,sizeof(c));
for(int i=1;i<=1;i++){ //最后大小是1*2
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++) add(c[i][j],ans[i][k]*b[k][j]);
}
}
memmove(b,c,sizeof(b));
printf("%lld\n",b[1][1]);
return 0;
}
1643:【例 3】Fibonacci 前 n 项和
1 0 0
1 1 1
1 1 0 这个是应该乘的转移矩阵
第一个矩阵是 1 1 0 第一位是到i的和,第二位是fi-1,第三位是fi-2),每次乘右边这个矩阵就是转移一次
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
/*
1 0 0
1 1 1
1 1 0 这个是应该乘的转移矩阵
第一个矩阵式 1 1 0 第一位是到i的和,第二位是fi-1,第三位是fi-2),每次乘右边这个矩阵就是转移一次
*/
int n;
LL power[5][5],a[5][5],c[5][5],ans[5][5];
LL mod;
void add(LL &x,LL y){
x+=y;
if(x>=mod) x-=mod;
return;
}
int main(){
scanf("%d",&n);
n-=1; //因为第一项和第二项都是1
scanf("%lld",&mod);
ans[1][1]=ans[1][2]=1; //ans[1][3]=0
a[1][1]=a[2][1]=a[2][2]=a[2][3]=a[3][1]=a[3][2]=1;
for(int i=1;i<=3;i++) power[i][i]=1;
//单位矩阵
while(n){ //计算ans数组
if(n&1){
memset(c,0,sizeof(c));
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++){
add(c[i][j],power[i][k]*a[k][j]%mod);
}
memmove(power,c,sizeof(power));
}
memset(c,0,sizeof(c));
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++){
add(c[i][j],a[i][k]*a[k][j]%mod);
}
memmove(a,c,sizeof(a));
n>>=1;
}
memset(c,0,sizeof(c));
for(int i=1;i<=1;i++){
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++) add(c[i][j],ans[i][k]*power[k][j]%mod);
}
memmove(ans,c,sizeof(c));
printf("%lld\n",ans[1][1]);
return 0;
}
1644:【例 4】佳佳的 Fibonacci

这个数组有不一样的了
我完全想不到。。。。
https://www.cnblogs.com/henry-1202/p/9932349.html
还有这个转移矩阵(人家随随便便就推出来了。。。
p[i] 1 1 0 0 p[i+1]
s[i] 0 1 1 0 s[i+1]
f[i] 0 0 1 1 f[i+1]
f[i-1]0 0 1 0 f[i]
f[i] = f[i-1]+f[i-2]
T[n] = f[1]+f[2]*2+f[3]*3+...+f[n]*n
S[n] = f[1]+f[2]+f[3]+...+f[n]
n*S[n] = n*f[1]+n*f[2]+n*f[3]+...+n*f[n]
设
--> P[n] = n*S[n]-T[n]
--> P[n] = (n-1)*f[1]+(n-2)*f[2]+...+(n-n)*f[n]
因为
--> P[n-1] = (n-1)*S[n]-T[n-1]
--> P[n-1] = (n-2)*f[1]+(n-3)*f[2]+...+(n-1-(n-1))*f[n-1]
且
--> S[n-1] = f[1]+f[2]+f[3]+....+f[n-1]
所以
P[n]=P[n-1]+S[n-1]
P[i] S[i] f[i] f[i-1]
1 0 0 0
1 1 0 0
0 1 1 1
0 1 1 0
*/
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
//我完全想不到。。。。
//https://www.cnblogs.com/henry-1202/p/9932349.html
/*
还有这个转移矩阵(人家随随便便就推出来了。。。
p[i] 1 1 0 0 p[i+1]
s[i] 0 1 1 0 s[i+1]
f[i] 0 0 1 1 f[i+1]
f[i-1]0 0 1 0 f[i]
f[i] = f[i-1]+f[i-2]
T[n] = f[1]+f[2]*2+f[3]*3+...+f[n]*n
S[n] = f[1]+f[2]+f[3]+...+f[n]
n*S[n] = n*f[1]+n*f[2]+n*f[3]+...+n*f[n]
设
--> P[n] = n*S[n]-T[n]
--> P[n] = (n-1)*f[1]+(n-2)*f[2]+...+(n-n)*f[n]
因为
--> P[n-1] = (n-1)*S[n]-T[n-1]
--> P[n-1] = (n-2)*f[1]+(n-3)*f[2]+...+(n-1-(n-1))*f[n-1]
且
--> S[n-1] = f[1]+f[2]+f[3]+....+f[n-1]
所以
P[n]=P[n-1]+S[n-1]
P[i] S[i] f[i] f[i-1]
1 0 0 0
1 1 0 0
0 1 1 1
0 1 1 0
*/
LL n,mod;
LL ans[5][5],power[5][5],a[5][5],c[5][5];
void add(LL &x,LL y){
x+=y;
if(x>=mod) x-=mod;
return;
}
int main(){
scanf("%lld",&n);
int nn=n;
n-=1;
scanf("%lld",&mod);
ans[1][2]=ans[1][3]=1;//0 1 1 0
for(int i=1;i<=4;i++) {
power[i][i]=1; //单位矩阵
}
a[1][1]=a[2][2]=a[2][1]=a[3][2]=a[3][3]=a[3][4]=a[4][2]=a[4][3]=1;
while(n){
if(n&1){
memset(c,0,sizeof(c));
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
for(int k=1;k<=4;k++)
add(c[i][j],power[i][k]*a[k][j]%mod);
memmove(power,c,sizeof(power));
}
memset(c,0,sizeof(c));
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
for(int k=1;k<=4;k++)
add(c[i][j],a[i][k]*a[k][j]%mod);
memmove(a,c,sizeof(a));
n>>=1;
}
memset(c,0,sizeof(c));
for(int i=1;i<=1;i++)
for(int j=1;j<=4;j++)
for(int k=1;k<=4;k++)
add(c[i][j],ans[i][k]*power[k][j]%mod);
memmove(ans,c,sizeof(ans));
//结果是ns[n]-p[n]
printf("%lld",(ans[1][2]*nn%mod-ans[1][1]+mod)%mod);
return 0;
}
1645:Fibonacci
没啥变化还是模板题,就是数据多组,不用看了
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
//这个是模板
//斐波那契数列取模
/*
(1)
1 0 * 1 1 = 1 1
1 0
(2)
1 1 * 1 1 = 2 1
1 0
(3)
2 1 * 1 1 = 3 2
1 0
所以第n项就是1 0 * (1,1)^n
(1,0)
用快速幂优化就是矩阵快速幂了
*/
LL n,mod;
LL a[3][3],b[3][3],ans[3][3],c[3][3];
void add(LL &x,LL y){
x=x+y;
x-=(x>=mod)?mod:0;
return;
}
// memmove用于拷贝字节,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。
//但是当目标区域与源区域没有重叠则和memcpy函数功能相同。
int main(){
mod=10000;
while(~scanf("%lld",&n)){
if(n==0){
printf("0\n");
continue;
}
if(n==-1) break;
n-=1;
a[1][1]=a[1][2]=a[2][1]=1;a[2][2]=0;
ans[1][1]=ans[2][2]=1; //ans是单位矩阵
ans[2][1]=ans[1][2]=0;
while(n){
if(n&1){ //快速幂
memset(c,0,sizeof(c));
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++) add(c[i][j],ans[i][k]*a[k][j]%mod);
}
}
memmove(ans,c,sizeof(ans)); //这个函数是实现字节的拷贝 把c放在ans里面
}
memset(c,0,sizeof(c));
//对a进行倍乘
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++) add(c[i][j],a[i][k]*a[k][j]%mod);
}
memmove(a,c,sizeof(a));
n>>=1;
}
//这个快速幂主要目的是求出ans数组,然后最后直接与b相乘
b[1][1]=1;b[1][2]=0;
memset(c,0,sizeof(c));
for(int i=1;i<=1;i++){ //最后大小是1*2
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++) add(c[i][j],ans[i][k]*b[k][j]);
}
}
memmove(b,c,sizeof(b));
printf("%lld\n",b[1][1]);
}
return 0;
}
1646:GT 考试

![]()
这个应该属于第(5)种,先推出dp方程式,然后用矩阵快速幂去优化
https://blog.csdn.net/jianglw1/article/details/98247505
https://www.cnblogs.com/gaojunonly1/p/10507823.html
这个解释德比较清楚,但是我还是没看懂,匹配那一部分,为什么要用到KMP
此题应该是先想到暴力的做法再用矩阵乘法优化的
所以暴力的思想很重要
dp[i][j]表示到第i位,匹配了j个的方案数
先预处理出f[i][j]表示已经匹配了i个,加一个数字变成匹配了j个方案数,i,j<=m-1,用kmp搞搞
转移就不难了,dp[i][j]+=dp[i-1][k]*f[k][j] 和矩阵乘法很像


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
/*
https://blog.csdn.net/jianglw1/article/details/98247505
https://www.cnblogs.com/gaojunonly1/p/10507823.html
这个解释德比较清楚,但是我还是没看懂,匹配那一部分,为什么要用到KMP
此题应该是先想到暴力的做法再用矩阵乘法优化的
所以暴力的思想很重要
dp[i][j]表示到第i位,匹配了j个的方案数
先预处理出f[i][j]表示已经匹配了i个,加一个数字变成匹配了j个方案数,i,j<=m-1,用kmp搞搞
转移就不难了,dp[i][j]+=dp[i-1][k]*f[k][j] 和矩阵乘法很像
*/
inline ll read()
{
ll s=0;
bool f=0;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<0)
{
putchar('-'); x=-x;
}
if(x<10)
{
putchar(x+'0'); return;
}
write(x/10);
putchar((x%10)+'0');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=100005,M=25;
int n,m,Mod;
int Num[25],f[25][25];
int ans[25][25],power[25][25],a[25][25],c[25][25];
inline void Ad(int &x,int y)
{
x+=y;
x-=(x>=Mod)?Mod:0;
return;
}
int Next[25];
inline void Pre_f()
{
int i,j=0;
Next[1]=0;
for(i=2;i<=m;i++)
{
while((Num[j+1]!=Num[i])&&j) j=Next[j];
if(Num[j+1]==Num[i]) j++;
Next[i]=j;
}
for(i=0;i<m;i++)
{
for(j=0;j<=9;j++)
{
int Now=i;
while((Num[Now+1]!=j)&&Now) Now=Next[Now];
if(Num[Now+1]==j) Now++;
f[i][Now]++;
}
}
/*
for(i=0;i<m;i++,puts(""))
{
for(j=0;j<m;j++) W(f[i][j]);
}
puts("");
*/
return;
}
int main()
{
int i,j,k,Sum=0;
R(n); R(m); R(Mod);
for(i=1;i<=m;i++)
{
char ch=' ';
while(!isdigit(ch)) ch=getchar();
Num[i]=ch-'0';
}
Pre_f();
ans[0][0]=1;
for(i=0;i<=m-1;i++) power[i][i]=1;
memmove(a,f,sizeof a);
while(n)
{
if(n&1)
{
memset(c,0,sizeof c);
for(i=0;i<=m-1;i++) for(j=0;j<=m-1;j++) for(k=0;k<=m-1;k++)
{
Ad(c[i][j],power[i][k]*a[k][j]%Mod);
}
memmove(power,c,sizeof power);
}
memset(c,0,sizeof c);
for(i=0;i<=m-1;i++) for(j=0;j<=m-1;j++) for(k=0;k<=m-1;k++)
{
Ad(c[i][j],a[i][k]*a[k][j]%Mod);
}
memmove(a,c,sizeof a);
n>>=1;
}
memset(c,0,sizeof c);
for(i=0;i<=0;i++) for(j=0;j<=m-1;j++) for(k=0;k<=m-1;k++)
{
Ad(c[i][j],ans[i][k]*power[k][j]%Mod);
}
memmove(ans,c,sizeof ans);
for(i=0;i<m;i++) Ad(Sum,ans[0][i]);
Wl(Sum);
return 0;
}
1647:迷路

这个就是类型(4)图论中的题
其实这里要先知道一个结论的,我不知道TAT
这个题初看没有什么头绪(dp失败. 我们联系一下邻接矩阵,
邻接矩阵一个很神奇的性质: 表示连通性的邻接矩阵的k次幂后的a[i][j]表示图中i–>j长度为k的路径条数,大概理解为:
从第i点出发到任意点的长度k-1道路条数(第i行) 与 任意点到j点的长度1的道路条数(第j列) 乘积和就是i–>j长度为k的路径条数
, 但是邻接矩阵只能处理边权为1的点, 这题需要转换. 我们把一个点i拆成更多的虚点,用来抵消部分边权的距离, 让它实际上以邻接矩阵的方式跑图. 假如点1到点2的边权为5,
把这条边拆成边权为1的5条边, 让点1在自己的虚点上先走4步, 最后到达2, 路径(1.0)->(1.1)->(1.2)->(1.3)->(1.4)->(2.0), 最后矩阵快速幂一下。
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=505;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
//https://www.cnblogs.com/gaojunonly1/p/10507823.html
//https://blog.csdn.net/jianglw1/article/details/98247593
/*
这个题初看没有什么头绪(dp失败. 我们联系一下邻接矩阵, 邻接矩阵一个很神奇的性质: 表示连通性的邻接矩阵的k次幂后的a[i][j]表示图中i–>j长度为k的路径条数,大概理解为:
从第i点出发到任意点的长度k-1道路条数(第i行) 与 任意点到j点的长度1的道路条数(第j列) 乘积和就是i–>j长度为k的路径条数
? 但是邻接矩阵只能处理边权为1的点, 这题需要转换. 我们把一个点i拆成更多的虚点,用来抵消部分边权的距离, 让它实际上以邻接矩阵的方式跑图. 假如点1到点2的边权为5,
把这条边拆成边权为1的5条边, 让点1在自己的虚点上先走4步, 最后到达2, 路径(1.0)->(1.1)->(1.2)->(1.3)->(1.4)->(2.0), 最后矩阵快速幂一下。
*/
int n,m,mod=2009,t;
struct node{
int mp[105][105];
node(){
memset(mp,0,sizeof(mp));
}
node operator * (const node &tt)const{
node ans;
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=m;k++)
ans.mp[i][j]=(ans.mp[i][j]+mp[i][k]*tt.mp[k][j]%mod)%mod;
return ans;
}
};
node poww(node a,int k){
node res;
for(int i=1;i<=m;i++) res.mp[i][i]=1;
while(k){
if(k&1){
res=res*a;
}
a=a*a;
k>>=1;
}
return res;
}
int main(){
scanf("%d %d",&n,&t);
m=9*n;
//总共的点数!!
node ans,base;
for(int i=1;i<=n;i++){ //每个点都拆为9个
for(int j=1;j<9;j++){
base.mp[(i-1)*9+j][(i-1)*9+j+1]=1; //连接拆点
}
}
int tmp;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%1d",&tmp); //!!!!!!!!这里,保证输入这个数只有一位!!!
if(tmp){
base.mp[(i-1)*9+tmp][(j-1)*9+1]=1; //在自己的链上跑tmp次到下个状态
}
}
}
ans=poww(base,t);
printf("%d\n",ans.mp[1][m-8]);
//最后一个点的1.0
return 0;
}
POJ 3735 Training little cats
//其实这是一道理解转移矩阵很好的一道题
//g 给1个 e 吃掉所以 s(i,j) 交换i和j的
/*
1 0 0 1 x ---> x+1
0 1 0 0 y ---> y
0 0 1 0 z ---> z
0 0 0 1 1 ---> 1
1 0 0 0 x ---> x
0 0 0 0 y ---> 0
0 0 1 0 z ---> z
0 0 0 1 1 ---> 1
1 0 0 0 x ---> x
0 0 1 0 y ---> z
0 1 0 0 z ---> y
0 0 0 1 1 ---> 1
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=110;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
//其实这是一道理解转移矩阵很好的一道题
//g 给1个 e 吃掉所以 s(i,j) 交换i和j的
/*
1 0 0 1 x ---> x+1
0 1 0 0 y ---> y
0 0 1 0 z ---> z
0 0 0 1 1 ---> 1
1 0 0 0 x ---> x
0 0 0 0 y ---> 0
0 0 1 0 z ---> z
0 0 0 1 1 ---> 1
1 0 0 0 x ---> x
0 0 1 0 y ---> z
0 1 0 0 z ---> y
0 0 0 1 1 ---> 1
*/
struct node{
LL mp[maxn][maxn];
node(){
memset(mp,0,sizeof(mp));
}
};
node e,ans;
int n,m,k;
node mul(node a,node b){
node res;
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
if(a.mp[i][j]) //优化,不然会超时
for(int k=0;k<=n;k++){
res.mp[i][k]+=(a.mp[i][j]*b.mp[j][k]);
}
}
}
return res;
}
//快速幂
node ksm(node a,int k){
node res;
for(int i=0;i<=n;i++) res.mp[i][i]=1;
while(k){
if(k&1){
res=mul(res,a);
}
a=mul(a,a);
k>>=1;
}
return res;
}
void inti(){
char w[2];
memset(e.mp,0,sizeof(e.mp));
//初始化为单位矩阵
int x,y;
for(int i=0;i<=n;i++) e.mp[i][i]=1;
while(k--){
scanf("%s",w);
if(w[0]=='g'){ //给一个
scanf("%d",&x);
x--; //eieieieieieiattention
e.mp[n][x]++;
}
else if(w[0]=='e'){ //吃完
scanf("%d",&x);
x--;
for(int i=0;i<=n;i++) e.mp[i][x]=0; //都要清0
}
else {
scanf("%d %d",&x,&y);
x--;y--;
if(x!=y){
for(int i=0;i<=n;i++){
swap(e.mp[i][x],e.mp[i][y]);
}
}
}
}
}
int main(){
while(~scanf("%d %d %d",&n,&m,&k)){
if(n==0&&m==0&&k==0) break;
inti();
ans=ksm(e,m); //变换矩阵做m次变化
for(int i=0;i<n;i++){
printf("%lld ",ans.mp[n][i]); //输出前n个
}
printf("\n");
}
return 0;
}
posted on
浙公网安备 33010602011771号