描述: 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储)。她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式: F[1][1]=1 F[i,j]=a*F[i][j-1]+b (j!=1) F[i,1]=c*F[i-1][m]+d (i!=1) 递推式中a,b,c,d都是给定的常数。 现在婷婷想知道F[n][m]的值是多少,请你帮助她。由于最终结果可能很大,你只需要输出F[n][m]除以1,000,000,007的余数。 输入: 一行有六个整数n,m,a,b,c,d。意义如题所述。 1<=N,M<=10^1000 000,a<=a,b,c,d<=10^9 输出: 包含一个整数,表示F[n][m]除以1,000,000,007的余数 样例输入 3 4 1 3 2 6 样例输出 85 一开始是想暴力或者使用矩阵乘法的,但暴力会发现有个10^1000000的n和m,而矩阵乘法我在写这题的上一题狠狠的让所有跟地址有关的东西全部报错了,再加上矩阵乘法本身也没学好,属于是学艺不精。 最后靠着学长的题解终于搞懂 这题一看很麻烦(实际上化简找规律也确实很麻烦)首先从行开始下手,不难得出 这一结论; 于是乎从第二行开始就麻烦起来了 根据推算 同理 最终可得 但这样看着便太繁琐了... 观察发现 这个式子出现较多,则令, 同时令, 最后可得 但因为n,m的大小,于是乎需要使用费马小定理: 费马小定理:假如 a 是一个整数, p是一个质数,那么 是 p 的倍数,也可以表示为 。如果 a不是 p的倍数的话,这个定理可以改写成我们常看的形式:。 将n,m改写后,将x,y,p,q按推算那样写出来即可 注意:当a=1||x=1时,是本题的特例,需要另外描述 另:在本题提交时候一直报错,最后发现是费马小定理简化需要另外自定义函数进行赋值(奇了怪了) #include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
string n,m;
long long a,b,c,d,n1=0,n2=0,m2=0,m1=0;
int l1,l2;
long long qpow(long long x,long long y)
{
long long res=1;
while(y)
{
if(y%2==1)res=res*x%mod;
x=x*x%mod;
y/=2;
}
return res;
}
void fm(long long &a1,long long &a2,string s,int l)
{
for(int i=0;i<l;i++)
{
a1=(a1*10+s[i]-'0')%mod;
a2=(a2*10+s[i]-'0')%(mod-1);
}
}
int main()
{
cin>>n>>m>>a>>b>>c>>d;
l1=n.size();
l2=m.size();
fm(n1,n2,n,l1);
fm(m1,m2,m,l2);
long long aa;
aa=qpow(a,m2-1);
long long x,y,p,q;
x=aa*c%mod;
y=aa*d%mod;
if(a!=1)p=b*(aa-1)%mod*qpow(a-1,mod-2)%mod;
else p=b*((m1-1+mod)%mod)%mod;
if(x!=1)q=(qpow(x,(n2-1+mod)%mod)-1+mod)%mod*qpow(x-1,mod-2)%mod;
else q=x*((n1-1+mod)%mod)%mod;
cout<<(qpow(x,(n2-1+mod)%mod)*(aa+p)%mod+(y+p)%mod*q%mod)%mod<<endl;
} |