bzoj 3240 (洛谷P1397): [Noi2013]矩阵游戏 (欧拉定理、数学)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sunshiness_s/article/details/81350213

题意

F ( i , j ) = { 1 i = 1 , j = 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 n m ,求 F ( n , m )


题解

我们先来化简这个式子

通过第一个式子,我们可以得到 f ( i , m ) = a m 1 f ( i , 1 ) + ( a m 2 + a m 3 + a + 1 ) b

重新考虑答案

f ( n , m ) = a m 1 f ( n , 1 ) + ( a m 2 + a m 3 + a + 1 ) b = a m 1 ( c f ( n 1 , m ) + d ) + ( a m 2 + a m 3 + a + 1 ) b = a m 1 c f ( n 1 , m ) + a m 1 d + ( a m 2 + a m 3 + a + 1 ) b

简化一波…令 p = ( a m 2 + a m 3 + + a + 1 ) b x = a m 1 c y = a m 1 d + p q = ( x n 2 + x n 3 + + x + 1 ) y (后面会有用)

那么,原式就等于

f ( n , m ) = a m 1 c f ( n 1 , m ) + a m 1 d + ( a m 2 + a m 3 + a + 1 ) b = x f ( n 1 , m ) + y = x ( a m 1 f ( n 1 , 1 ) + p ) + y = x a m 1 f ( n 1 , 1 ) + x p + y = x a m 1 ( c f ( n 2 , m ) + d ) + x p + y = x a m 1 c f ( n 2 , m ) + x a m 1 d + x p + y = x 2 f ( n 2 , m ) + ( x + 1 ) y = x n 1 f ( 1 , m ) + ( x n 2 + x n 3 + + x + 1 ) y = a m 1 x n 1 + x n 1 p + q

显然 p q 可以用等比数列求出(等比为 1 的时候另行讨论)

扫描二维码关注公众号,回复: 3171460 查看本文章

然而 a m 1 x n 1 就不能直接算了

通过费马小定理 a ( p 1 ) 1 ( m o d p ) , 所以 a p = a ( p m o d ( k 1 ) ) ( m o d k )


代码

#include <cstdio>
#include <cstring>
#define mod 1000000007
#define N 1000005
#define ll long long
char str1[N];
int n,m,n1,m1,a,b,c,d;
int qpow(int x,int y){
    int t=1;
    while(y){
        if(y&1) t=(ll)t*x%mod;
        x=(ll)x*x%mod;y>>=1; 
    }return t;
}
int main(){
    freopen("a.in","r",stdin);

    scanf("%s",str1+1);
    n=0,n1=0;int nn=strlen(str1+1);
    for(int i=1;i<=nn;i++) n=((ll)n*10+str1[i]-'0')%(mod-1),n1=((ll)n1*10+str1[i]-'0')%mod;
    n=(n-1+mod-1)%(mod-1);n1=(n1-1+mod)%mod;
    scanf("%s",str1+1);
    m=0,m1=0;nn=strlen(str1+1);
    for(int i=1;i<=nn;i++) m=((ll)m*10+str1[i]-'0')%(mod-1),m1=((ll)m1*10+str1[i]-'0')%mod;
    m=(m-1+mod-1)%(mod-1);m1=(m1-1+mod)%mod;

    scanf("%d%d%d%d",&a,&b,&c,&d);
    int am=qpow(a,m),x=(ll)am*c%mod,p;
    if(a==1) p=(ll)m1*b%mod;
    else p=(ll)b*(am-1+mod)%mod*qpow(a-1,mod-2)%mod;
    int xn=qpow(x,n),y=((ll)am*d%mod+p)%mod,q;
    if(x==1) q=(ll)n1*y%mod;
    else q=(ll)y*(xn-1+mod)%mod*qpow(x-1,mod-2)%mod;

    printf("%d\n",(((ll)am*xn%mod+(ll)xn*p%mod)%mod+q)%mod);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunshiness_s/article/details/81350213