矩阵快速幂专题(矩阵快速幂入门、矩阵构造法、数论规律题)

181 篇文章 0 订阅
79 篇文章 0 订阅


Link1:http://acm.hdu.edu.cn/showproblem.php?pid=1575


Tr A

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3628    Accepted Submission(s): 2705


Problem Description
A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。
 

Input
数据的第一行是一个T,表示有T组数据。
每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据。接下来有n行,每行有n个数据,每个数据的范围是[0,9],表示方阵A的内容。
 

Output
对应每组数据,输出Tr(A^k)%9973。
 

Sample Input
  
  
2 2 2 1 0 0 1 3 99999999 1 2 3 4 5 6 7 8 9
 

Sample Output
  
  
2 2686
 

Author
xhd
 

Source
 


AC code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
const int INF=0x3f3f3f3f;
//----以下为矩阵快速幂模板-----// 
const int mod=9973;
const int NUM=11;//定义矩阵能表示的最大维数 
int N;//N表示矩阵的维数,以下的矩阵加法、乘法、快速幂都是按N维矩阵运算的 
struct Mat{//矩阵的类
	int a[NUM][NUM];
	void init()//将其初始化为单位矩阵  
	{
		memset(a,0,sizeof(a));
		for(int i=0;i<NUM;i++)
		{
			a[i][i]=1;
		}
	}
};
Mat add(Mat a,Mat b)//(a+b)%mod  矩阵加法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=a.a[i][j]+b.a[i][j];
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat mul(Mat a,Mat b) //(a*b)%mod  矩阵乘法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=0;
			for(int k=0;k<N;k++)
			{
				ans.a[i][j]+=a.a[i][k]*b.a[k][j];
			}
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat power(Mat a,int num)//(a^n)%mod  矩阵快速幂 
{
	Mat ans;
	ans.init();
	while(num)
	{
		if(num&1)
		{
			ans=mul(ans,a);
		}
		num>>=1;
		a=mul(a,a);
	}
	return ans;
}
Mat pow_sum(Mat a,int num)//(a+a^2+a^3....+a^n)%mod 矩阵的幂和
{
	int m;
	Mat ans,pre;
	if(num==1)
		return a;
	m=num/2;
	pre=pow_sum(a,m);
	ans=add(pre,mul(pre,power(a,m)));
	if(num&1)
		ans=add(ans,power(a,num));
	return ans;
}
void output(Mat a)//输出矩阵 
{
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			printf("%d%c",a.a[i][j],j==N-1?'\n':' ');
		}
	}
}
//----以上为矩阵快速幂模板-----// 
int main()
{
	int t,n,k,ans,i,j;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&k);
		N=n;
		ans=0;
		Mat a,temp;
		for(i=0;i<N;i++)
		{
			for(j=0;j<N;j++)
			{
				scanf("%d",&a.a[i][j]);
			}
		}
		temp=power(a,k);
		for(i=0;i<N;i++)
		{
			ans=(ans+temp.a[i][i])%mod;
		}
		printf("%d\n",ans);
	}
	return 0;
}

 


Link2:http://poj.org/problem?id=3070


Fibonacci
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10815 Accepted: 7683

Description

In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …

An alternative formula for the Fibonacci sequence is

.

Given an integer n, your goal is to compute the last 4 digits of Fn.

Input

The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ n ≤ 1,000,000,000). The end-of-file is denoted by a single line containing the number −1.

Output

For each test case, print the last four digits of Fn. If the last four digits of Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print Fn mod 10000).

Sample Input

0
9
999999999
1000000000
-1

Sample Output

0
34
626
6875

Hint

As a reminder, matrix multiplication is associative, and the product of two 2 × 2 matrices is given by

.

Also, note that raising any 2 × 2 matrix to the 0th power gives the identity matrix:

.

Source




注意:题目中给出的那个斐波那契数列的矩阵表示规律:

这个要记住!!!有时做一些规律题时涉及求F(n)时会用到!!!可利用矩阵快速幂求矩阵{1,1,1,0}的n次幂,在求得的矩阵中,第一行第二列的元素就是F(n)!!!下面有一些题就是利用这个{1,1,1,0}矩阵做的。


AC  code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
const int INF=0x3f3f3f3f;
//----以下为矩阵快速幂模板-----// 
const int mod=10000;
const int NUM=11;//定义矩阵能表示的最大维数 
int N;//N表示矩阵的维数,以下的矩阵加法、乘法、快速幂都是按N维矩阵运算的 
struct Mat{//矩阵的类
	int a[NUM][NUM];
	void init()//将其初始化为单位矩阵  
	{
		memset(a,0,sizeof(a));
		for(int i=0;i<NUM;i++)
		{
			a[i][i]=1;
		}
	}
};
Mat add(Mat a,Mat b)//(a+b)%mod  矩阵加法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=a.a[i][j]+b.a[i][j];
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat mul(Mat a,Mat b) //(a*b)%mod  矩阵乘法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=0;
			for(int k=0;k<N;k++)
			{
				ans.a[i][j]+=a.a[i][k]*b.a[k][j];
			}
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat power(Mat a,int num)//(a^n)%mod  矩阵快速幂 
{
	Mat ans;
	ans.init();
	while(num)
	{
		if(num&1)
		{
			ans=mul(ans,a);
		}
		num>>=1;
		a=mul(a,a);
	}
	return ans;
}
Mat pow_sum(Mat a,int num)//(a+a^2+a^3....+a^n)%mod 矩阵的幂和
{
	int m;
	Mat ans,pre;
	if(num==1)
		return a;
	m=num/2;
	pre=pow_sum(a,m);
	ans=add(pre,mul(pre,power(a,m)));
	if(num&1)
		ans=add(ans,power(a,num));
	return ans;
}
void output(Mat a)//输出矩阵 
{
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			printf("%d%c",a.a[i][j],j==N-1?'\n':' ');
		}
	}
}
//----以上为矩阵快速幂模板-----// 
int main()
{
	int t,n,k,ans,i,j;
	while(scanf("%d",&n)!=EOF)
	{
		if(n==-1)
			break;
		Mat a,f;
		N=2;
	    a.a[0][0]=a.a[0][1]=a.a[1][0]=1;
	    a.a[1][1]=0;
		f=power(a,n);
		printf("%d\n",f.a[0][1]);
	 } 
	return 0;
}

 



Link3:http://acm.hdu.edu.cn/showproblem.php?pid=1568

Fibonacci

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3970    Accepted Submission(s): 1830


Problem Description
2007年到来了。经过2006年一年的修炼,数学神童zouyu终于把0到100000000的Fibonacci数列
(f[0]=0,f[1]=1;f[i] = f[i-1]+f[i-2](i>=2))的值全部给背了下来。
接下来,CodeStar决定要考考他,于是每问他一个数字,他就要把答案说出来,不过有的数字太长了。所以规定超过4位的只要说出前4位就可以了,可是CodeStar自己又记不住。于是他决定编写一个程序来测验zouyu说的是否正确。
 

Input
输入若干数字n(0 <= n <= 100000000),每个数字一行。读到文件尾。
 

Output
输出f[n]的前4个数字(若不足4个数字,就全部输出)。
 

Sample Input
  
  
0 1 2 3 4 5 35 36 37 38 39 40
 

Sample Output
  
  
0 1 1 2 3 5 9227 1493 2415 3908 6324 1023
 

Author
daringQQ
 

Source
 

解题思想:运用斐波那契通项公式:F(n) = (((1+Sqrt(5))/2)^n - ((1-Sqrt(5))/2)^n)*1/Sqrt(5)。我们需要记住那个公式!!!
因为(1-sqrt(5))/2的绝对值小于1
所以当i较大的时候,往往可以忽略掉这一项 
f(i)≈((1+Sqrt(5))/2)^n/sqrt(5);
所以,刚才列举出的HDOJ的1568,可以很简单的20以内直接求解,20以上采用这个公式,或者用log(N)求幂的算法求解 。
取前4位数主要采用取对数的方法求,算法思想如下:

fibonacci公式:


对公式取对数:


最后一项小于0并且很小可以不用计算。

假设给出一个数10234432,

那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7;

log10(1.0234432)就是log10(10234432)的小数部分.

10^0.010063744=1.023443198



AC code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
#include<cmath>
#define LL long long
#define MAXN 1000010
using namespace std;
double f[33];
int main()
{
	//freopen("D:\in.txt","r",stdin);
	int n,i;
	f[0]=0;
	f[1]=1;
	for(i=2;i<=20;i++)
	{
		f[i]=f[i-1]+f[i-2];
	}
	//printf("%.0f\n",f[20]);
	while(scanf("%d",&n)!=EOF)
	{
		if(n<=20)
			printf("%.0f\n",f[n]);
		else
		{
			int answer;
			double t=-0.5*log10(5.0)+n*log10(0.5*(1.0+sqrt(5.0)));
			double ans=t-floor(t);
			ans=pow(10,ans);
			answer=(int)(ans*1000);
			printf("%d\n",answer);
		}
	}
	return 0;
 } 






Fibonacci Again

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 44266    Accepted Submission(s): 21120


Problem Description
There are another kind of Fibonacci numbers: F(0) = 7, F(1) = 11, F(n) = F(n-1) + F(n-2) (n>=2).
 

Input
Input consists of a sequence of lines, each containing an integer n. (n < 1,000,000).
 

Output
Print the word "yes" if 3 divide evenly into F(n).

Print the word "no" if not.
 

Sample Input
   
   
0 1 2 3 4 5
 

Sample Output
   
   
no no yes no no no
 

Author
Leojay
 


AC code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
const int INF=0x3f3f3f3f;
//----以下为矩阵快速幂模板-----// 
const int mod=3;//模3,故这里改为3即可 
const int NUM=11;//定义矩阵能表示的最大维数 
int N;//N表示矩阵的维数,以下的矩阵加法、乘法、快速幂都是按N维矩阵运算的 
struct Mat{//矩阵的类
	int a[NUM][NUM];
	void init()//将其初始化为单位矩阵  
	{
		memset(a,0,sizeof(a));
		for(int i=0;i<NUM;i++)
		{
			a[i][i]=1;
		}
	}
};
Mat add(Mat a,Mat b)//(a+b)%mod  矩阵加法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=a.a[i][j]+b.a[i][j];
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat mul(Mat a,Mat b) //(a*b)%mod  矩阵乘法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=0;
			for(int k=0;k<N;k++)
			{
				ans.a[i][j]+=a.a[i][k]*b.a[k][j];
			}
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat power(Mat a,int num)//(a^n)%mod  矩阵快速幂 
{
	Mat ans;
	ans.init();
	while(num)
	{
		if(num&1)
		{
			ans=mul(ans,a);
		}
		num>>=1;
		a=mul(a,a);
	}
	return ans;
}
Mat pow_sum(Mat a,int num)//(a+a^2+a^3....+a^n)%mod 矩阵的幂和
{
	int m;
	Mat ans,pre;
	if(num==1)
		return a;
	m=num/2;
	pre=pow_sum(a,m);
	ans=add(pre,mul(pre,power(a,m)));
	if(num&1)
		ans=add(ans,power(a,num));
	return ans;
}
void output(Mat a)//输出矩阵 
{
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			printf("%d%c",a.a[i][j],j==N-1?'\n':' ');
		}
	}
}
//----以上为矩阵快速幂模板-----// 
int main()
{
	int t,n,k,i,j;
	while(scanf("%d",&n)!=EOF)
	{
		if(n==-1)
			break;
		if(n==0||n==1)
		{
			printf("no\n");
		}
		else
		{
			Mat a,f,fa,ans;
			N=2;
			fa.a[0][0]=11;
			fa.a[0][1]=7;
		    a.a[0][0]=a.a[0][1]=a.a[1][0]=1;
		    a.a[1][1]=0;
			f=power(a,n-1);
			for(int i=0;i<1;i++)
			{
				for(int j=0;j<N;j++)
				{
					ans.a[i][j]=0;
					for(int k=0;k<N;k++)
					{
						ans.a[i][j]=(ans.a[i][j]+fa.a[i][k]*f.a[k][j])%3;
					}
				}
			}
			//printf("%d\n",ans.a[0][0]);
			if(ans.a[0][0]%3==0)
				printf("yes\n");
			else
			{
				printf("no\n");
			}
		}	
	 } 
	return 0;
}

 




Gauss Fibonacci

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2796    Accepted Submission(s): 1158


Problem Description
Without expecting, Angel replied quickly.She says: "I'v heard that you'r a very clever boy. So if you wanna me be your GF, you should solve the problem called GF~. "
How good an opportunity that Gardon can not give up! The "Problem GF" told by Angel is actually "Gauss Fibonacci".
As we know ,Gauss is the famous mathematician who worked out the sum from 1 to 100 very quickly, and Fibonacci is the crazy man who invented some numbers.

Arithmetic progression:
g(i)=k*i+b;
We assume k and b are both non-nagetive integers.

Fibonacci Numbers:
f(0)=0
f(1)=1
f(n)=f(n-1)+f(n-2) (n>=2)

The Gauss Fibonacci problem is described as follows:
Given k,b,n ,calculate the sum of every f(g(i)) for 0<=i<n
The answer may be very large, so you should divide this answer by M and just output the remainder instead.
 

Input
The input contains serveral lines. For each line there are four non-nagetive integers: k,b,n,M
Each of them will not exceed 1,000,000,000.
 

Output
For each line input, out the value described above.
 

Sample Input
   
   
2 1 4 100 2 0 4 100
 

Sample Output
   
   
21 12
 

Author
DYGG
 

Source
 


题意: 给出k,b,n(0<=i<n),确定出g(i),进而算出Fibonacci数列的第g(i)项,最后将所有的项求和。

分析:看到数据的范围,我们就应该想到普通的暴力是不可取的,所以这道题需要解决两个问题,一个是如何快速的计算Fibonacci数列的第g(i)项,二是如何快速的将它们相加求和。

首先来解决第一个问题,本文的主题不就是快速的计算递推式的任意一项吗?所以,先让我们来找找前面的提到过的构造矩阵,从数列的递推式出发:f(n)= f(n-1)+ f(n-2),我们换一个简洁一些的等式:c = a + b(c是本项,a是后第一项,b是后第二项)。很明显,我们最后所得到的矩阵中必须要包含a+b一项,因为这正是我们想要计算的,同时我们的初始矩阵也不难想到,必须要有a和b,这样才能得到下一项c,那么关键就是构造矩阵了,其实反推一下就可以了,具体看的图:。如此一来只需要将上面第一个矩阵开i次幂,然后乘上第二个矩阵,就可以得到包含Fibonacci数列第i项的第i个矩阵了,其中a=0,b=1。(即利用矩阵快速幂求矩阵{1,1,1,0}的n次幂,在求得的矩阵中,第一行第二列的元素就是Fibonacci数列第n项F(n)

接下来需要解决第二个问题,由于g(i)= k*i + b的,所以题目要求计算的就是f(b)+ f(k+b)+ f(k*2+b)+ ... + f(k*(n-1)+b),依据上面的构造矩阵,我们用矩阵A重写前面的等式,即:A^b+ A^(k+b)+ A^(k*2+b)+ ... + A^(k*(n-1)+b),继续变形:A^b*(1+ A^k+ A^(k*2)+ ... + A^(k*(n-1)),令矩阵B=A^k,那么A^b*(1+ B ^1+ B^2)+ ... + B^(n-1)),结果已经很明显了,还记得二分吗?括号里面的和不正是上一次我们写过的二分求和么。到此,结果就可以快速的计算出来了。


AC code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
const int INF=0x3f3f3f3f;
//----以下为矩阵快速幂模板-----// 
//const int mod=3;//模3,故这里改为3即可 
int mod;
const int NUM=11;//定义矩阵能表示的最大维数 
int N;//N表示矩阵的维数,以下的矩阵加法、乘法、快速幂都是按N维矩阵运算的 
struct Mat{//矩阵的类
	LL a[NUM][NUM];
	void init()//将其初始化为单位矩阵  
	{
		memset(a,0,sizeof(a));
		for(int i=0;i<NUM;i++)
		{
			a[i][i]=1;
		}
	}
};
Mat add(Mat a,Mat b)//(a+b)%mod  矩阵加法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=(a.a[i][j]%mod)+(b.a[i][j]%mod);
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat mul(Mat a,Mat b) //(a*b)%mod  矩阵乘法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=0;
			for(int k=0;k<N;k++)
			{
				ans.a[i][j]=(ans.a[i][j]%mod)+(a.a[i][k]%mod)*(b.a[k][j]%mod);
			}
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat power(Mat a,int num)//(a^n)%mod  矩阵快速幂 
{
	Mat ans;
	ans.init();
	while(num)
	{
		if(num&1)
		{
			ans=mul(ans,a);
		}
		num>>=1;
		a=mul(a,a);
	}
	return ans;
}
Mat pow_sum(Mat a,int num)//(a+a^2+a^3....+a^n)%mod 矩阵的幂和
{
	int m;
	Mat ans,pre;
	if(num==1)
		return a;
	m=num/2;
	pre=pow_sum(a,m);
	ans=add(pre,mul(pre,power(a,m)));
	if(num&1)
		ans=add(ans,power(a,num));
	return ans;
}
void output(Mat a)//输出矩阵 
{
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			printf("%lld%c",a.a[i][j],j==N-1?'\n':' ');
		}
	}
}
//----以上为矩阵快速幂模板-----// 
int main()
{
	int k,b,n,m;
	while(scanf("%d%d%d%d",&k,&b,&n,&m)!=EOF)
	{
		Mat A,B,E,ans;
		N=2;
		mod=m;
		A.a[0][0]=A.a[0][1]=A.a[1][0]=1;
		A.a[1][1]=0;
		E.init();
		B=power(A,k);
		ans=mul(power(A,b),(add(E,pow_sum(B,n-1))));
		printf("%lld\n",ans.a[0][1]);
	}
	return 0;
}

 


Link6:http://acm.hdu.edu.cn/showproblem.php?pid=1757


A Simple Math Problem

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3485    Accepted Submission(s): 2101


Problem Description
Lele now is thinking about a simple function f(x).

If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .

Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
 

Input
The problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
 

Output
For each case, output f(k) % m in one line.
 

Sample Input
  
  
10 9999 1 1 1 1 1 1 1 1 1 1 20 500 1 0 1 0 1 0 1 0 1 0
 

Sample Output
  
  
45 104
 

Author
linle
 

Source
 
解题思想:
【f(n) f(n-1) f(n-2) f(n-3) f(n-4) f(n-5) f(n-6) f(n-7) f(n-8) f(n-9)】=【 f(9) f(8) f(7) f(6) f(5) f(4) f(3) f(2) f(1) f(0)】*

^(n-9);




AC code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define LL long long
#define MAXN 1000010
using namespace std;
const int INF=0x3f3f3f3f;
//----以下为矩阵快速幂模板-----// 
//const int mod=3;//模3,故这里改为3即可 
int mod;
const int NUM=12;//定义矩阵能表示的最大维数 
int N;//N表示矩阵的维数,以下的矩阵加法、乘法、快速幂都是按N维矩阵运算的 
struct Mat{//矩阵的类
	LL a[NUM][NUM];
	void init()//将其初始化为单位矩阵  
	{
		memset(a,0,sizeof(a));
		for(int i=0;i<NUM;i++)
		{
			a[i][i]=1;
		}
	}
};
Mat add(Mat a,Mat b)//(a+b)%mod  矩阵加法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=(a.a[i][j]%mod)+(b.a[i][j]%mod);
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat mul(Mat a,Mat b) //(a*b)%mod  矩阵乘法  
{
	Mat ans;
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			ans.a[i][j]=0;
			for(int k=0;k<N;k++)
			{
				ans.a[i][j]=(ans.a[i][j]%mod)+(a.a[i][k]%mod)*(b.a[k][j]%mod);
			}
			ans.a[i][j]%=mod;
		}
	}
	return ans;
}
Mat power(Mat a,int num)//(a^n)%mod  矩阵快速幂 
{
	Mat ans;
	ans.init();
	while(num)
	{
		if(num&1)
		{
			ans=mul(ans,a);
		}
		num>>=1;
		a=mul(a,a);
	}
	return ans;
}
Mat pow_sum(Mat a,int num)//(a+a^2+a^3....+a^n)%mod 矩阵的幂和
{
	int m;
	Mat ans,pre;
	if(num==1)
		return a;
	m=num/2;
	pre=pow_sum(a,m);
	ans=add(pre,mul(pre,power(a,m)));
	if(num&1)
		ans=add(ans,power(a,num));
	return ans;
}
void output(Mat a)//输出矩阵 
{
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			printf("%lld%c",a.a[i][j],j==N-1?'\n':' ');
		}
	}
}
//----以上为矩阵快速幂模板-----// 
int main()
{
	int k,m,i,j,kk;
	LL a[11];
	while(scanf("%d%d",&kk,&m)!=EOF)
	{
		for(i=0;i<10;i++)
		{
			scanf("%lld",&a[i]);
		}
		if(kk<10)
			printf("%d\n",k%m);
		else
		{
			Mat A,B,mi,ans;
			N=10;
			mod=m;
			memset(A.a,0,sizeof(A.a));
			memset(B.a,0,sizeof(B.a));
			for(i=0;i<10;i++)
			{
				A.a[0][i]=9-i;
				B.a[i][0]=a[i];
				B.a[i][i+1]=1;
			}
			//output(A);
		    //output(B);
			B=power(B,kk-9);
			for(int i=0;i<1;i++)
			{
				for(int j=0;j<N;j++)
				{
					ans.a[i][j]=0;
					for(int k=0;k<N;k++)
					{
						ans.a[i][j]=(ans.a[i][j]%mod)+(A.a[i][k]%mod)*(B.a[k][j]%mod);
					}
					ans.a[i][j]%=mod;
				}
			}
			printf("%lld\n",ans.a[0][0]%mod);
		}
	}
	return 0;
}

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值