标签:begin end 游戏 cdot 矩阵 phi bmatrix NOI2013 Matrix
做题时间:2022.7.4
\(【题目描述】\)
给定正整数 \(a,b,c,d(a,b,c,d\leq 10^9)\) ,有一个 \(n\) 行 \(m\) 列( \(1\leq n,m\leq 10^{1000000}\) )的矩阵 \(F\) ,满足:
\[F_{1,1}=1 \]\[F_{i,j}=a\cdot F_{i,j-1}+b(j\neq 1) \]\[F_{i,1}=c\cdot F_{i-1,m}+d(i\neq 1) \]求 \(F_{n,m}\mod 10^9+7\) 的值。
\(【输入格式】\)
一行 \(n,m,a,b,c,d\)
\(【输出格式】\)
一行一个数表示 \(F_{n,m}\mod 10^9+7\)
\(【考点】\)
矩阵快速幂,欧拉函数
\(【做法】\)
看数据范围可知要使用矩阵快速幂,同时递推式表明用第二个式子确定好当前行第1列的数字后,第m列的数字即可用第一个式子套矩阵快速幂快速求出,而下一行第1列的数字又和这一行第m列有关, 因此可以考虑将两个式子合并 。
- 第一个式子:
就有:
\[\begin{bmatrix} F_{n,m} \\ 1 \\ \end{bmatrix} \cdot \begin{bmatrix} a & b\\ 0 & 1 \end{bmatrix}^{m-1}= \begin{bmatrix} F_{n,1}\\ 1 \end{bmatrix} \]这里我们发现,不能直接求出的 \(F_{n,1}\) 可以用第二个式子带入。
- 第二个式子:
就有:
\[\begin{bmatrix} F_{1,m} \\ 1 \\ \end{bmatrix} \cdot \begin{bmatrix} c & d\\ 0 & 1 \end{bmatrix}= \begin{bmatrix} F_{n,1}\\ 1 \end{bmatrix} \]这里我们发现,第一个式子中不能直接求出的 \(F_{n,1}\) 可以用第二个式子带入,得到:
\[\begin{bmatrix} F_{1,m} \\ 1 \\ \end{bmatrix} \cdot \begin{bmatrix} c & d\\ 0 & 1 \end{bmatrix}^{n-1} \cdot \begin{bmatrix} a & b\\ 0 & 1\\ \end{bmatrix}^{m-1}= \begin{bmatrix} F_{n,1}\\ 1 \end{bmatrix} \]这个式子中不能直接求出的 \(F_{1,m}\) 又可以带回第一个式子,得到:
\[\begin{bmatrix} f_{1,1}\\ 1 \end{bmatrix} \cdot \begin{bmatrix} a & b\\ 0 & 1 \\ \end{bmatrix}^{2m-2} \cdot \begin{bmatrix} c & d\\ 0 & 1 \end{bmatrix}^{n-1} \cdot = \begin{bmatrix} F_{n,1}\\ 1 \end{bmatrix} \]直接用矩阵快速幂即可。
对于输入而言,根据欧拉定理:
\[a^x\equiv a^{x\mod \phi(p)} \pmod p \]我们用字符串读入\(n,m\) ,然后直接对 \(\phi(10^9+7)=10^9+6\) 取余即可。
注意 :在 \(a=1\) 时,原来作为底数的矩阵主对角线均为1,相当于数字1,此时欧拉定理不适用,不能模 \(\phi(p)\) 而应当模 \(p\)
\(【代码】\)
#include<cstdio>
#include<cstring>
#include<iomanip>
using namespace std;
typedef long long ll;
const ll phi=1e9+6,N=1e6+50,MOD=1e9+7;
struct Matrix{
ll a[3][3];
Matrix(){memset(a,0,sizeof(a));}
Matrix operator *(const Matrix x){
Matrix ans;
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++){
ans.a[i][j]=(ans.a[i][j]+a[i][k]*x.a[k][j]%MOD)%MOD;
}
}
}
return ans;
}
}A1,A2,A3;
char nn[N],mm[N];
ll a,b,c,d,n,m;
void Pre()//字符串转化为数字
{
int lenn=strlen(nn+1);
int lenm=strlen(mm+1);
ll pow=1;
for(int i=lenn;i>=1;i--){
n=(n+pow*(nn[i]-48));
pow*=10;
if(a==1) n%=MOD,pow%=MOD;//特判底数矩阵为1的情况
else n%=phi,pow%=phi;
}
pow=1;
for(int i=lenm;i>=1;i--){
m=(m+pow*(mm[i]-48));
pow*=10;
if(a==1) m%=MOD,pow%=MOD;
else m%=phi,pow%=phi;
}
}
Matrix FastPow(Matrix x,ll b)//矩阵快速幂
{
Matrix ans;
ans.a[1][1]=ans.a[2][2]=1;
while(b){
if(b&1) ans=ans*x;
x=x*x;
b>>=1;
}
return ans;
}
int main()
{
scanf("%s%s",nn+1,mm+1);
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
Pre();
A1.a[1][1]=A1.a[1][2]=1;
A2.a[1][1]=a,A2.a[1][2]=0,A2.a[2][1]=b,A2.a[2][2]=1;
A3.a[1][1]=c,A3.a[1][2]=0,A3.a[2][1]=d,A3.a[2][2]=1;
//赋初值
Matrix x=FastPow(A2,(2*m-1)%phi);
Matrix tmp=FastPow(A2,(m-1)%phi)*A3;
Matrix ans=A1*FastPow(tmp,(n-1)%phi)*FastPow(A2,(m-1)%phi);
printf("%lld\n",ans.a[1][1]%MOD);
return 0;
}
标签:begin,end,游戏,cdot,矩阵,phi,bmatrix,NOI2013,Matrix 来源: https://www.cnblogs.com/Unlimited-Chan/p/16448266.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。