TZOJ 4954 矩阵游戏 快速幂+费马定理

描述:

婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的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,而矩阵乘法我在写这题的上一题狠狠的让所有跟地址有关的东西全部报错了,再加上矩阵乘法本身也没学好,属于是学艺不精。

最后靠着学长的题解终于搞懂

这题一看很麻烦(实际上化简找规律也确实很麻烦)首先从行开始下手,不难得出

\int 1,m=a^{m-1}+b*\sum_{i=0}^{m-2}a^{i}这一结论;

于是乎从第二行开始就麻烦起来了

根据推算

\int 2,m=a^{m-1}*(a^{m-1}*c+b*\sum_{i=0}^{m-2}a^{i})+a^{m-1}d+b*\sum_{i=0}^{m-2}a^{i}

同理 最终可得

\int n,m= (a^{m-1}*c)^{m-1}*(a^{m-1}+b\sum_{i=0}^{m-2}a^{i})+(a^{m-1}*d+b\sum_{i=0}^{m-2}a^{i})*[(a^{m-1}*c)^{m-2}+(a^{m-1}*c)^{m-3}...+1]

但这样看着便太繁琐了...

观察发现

a^{m-1}这个式子出现较多,则令x=a^{m-1}*cy=a^{m-1}*d

同时令p=b\sum_{i=0}^{m-2}ai,q=\sum_{i=0}^{n-2}x

最后可得\int n,m=x^{n-1}*(a_{m-1}+p)+(y+p)*q

但因为n,m的大小,于是乎需要使用费马小定理:

费马小定理:假如 a 是一个整数, p是一个质数,那么a^{p}-a 是 p 的倍数,也可以表示为 a^p\equiva(mod p)。如果 a不是 p的倍数的话,这个定理可以改写成我们常看的形式:a^{p-1}\equiv 1(mod 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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值