bzoj 3240: [Noi2013]矩阵游戏

Description

婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储)。她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式:

F[1][1]=1
F[i,j]=aF[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的余数。

Solution

这题可以暴力矩乘跑过去
设初始矩阵为 \(A\),列转移矩阵为 \(B\),行转移矩阵为 \(C\)
那么答案就是 \(A*(B^{m-2}*C)^{n-2}*B\)

矩乘要用十进制快速幂,和二进制差不多,这一位是多少就乘多少次就行了

#include<bits/stdc++.h>
using namespace std;
#define RG register
const int mod=1e9+7;
struct mat{
    int a[2][2];
    mat(){memset(a,0,sizeof(a));}
    inline mat operator *(const mat &p){
        mat ret;
        for(RG int i=0;i<2;i++)
            for(RG int j=0;j<2;j++)
                for(RG int k=0;k<2;k++)
                    ret.a[i][j]=(ret.a[i][j]+1ll*a[i][k]*p.a[k][j])%mod;
        return ret;
    }
};
const int N=1e6+10;
char s1[N],s2[N];
inline void ksm(mat &S,mat T,int k){
    while(k){
        if(k&1)S=S*T;
        T=T*T;k>>=1;
    }
}
inline mat mul(mat S,mat T,char *s,int len){
    for(RG int i=len;i>=1;i--){
        ksm(S,T,s[i]-48);
        if(i>1)ksm(T,T,9);
    }
    return S;
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  scanf("%s%s",s2+1,s1+1);
  int a,b,c,d,len;
  cin>>a>>b>>c>>d;
  if(strlen(s1+1)==1 && s1[1]=='1' && strlen(s2+1)==1 && s2[1]=='1')
      puts("1"),exit(0);

  mat S,T,O,R;
  if(strlen(s1+1)==1 && s1[1]=='1'){
      S.a[0][0]=S.a[0][1]=1;S.a[1][0]=S.a[1][1]=0;
      T.a[0][0]=c;T.a[1][0]=d;T.a[1][1]=1;
      len=strlen(s2+1);s2[len]--;
      for(int i=len;i>=1;i--)if(s2[i]<'0')s2[i]+=10,s2[i-1]--;else break;
      S=mul(S,T,s2,len);
      cout<<S.a[0][0]<<endl;
      return 0;
  }
  if(strlen(s2+1)==1 && s2[1]=='1'){
      S.a[0][0]=S.a[0][1]=1;S.a[1][0]=S.a[1][1]=0;
      T.a[0][0]=a;T.a[1][0]=b;T.a[1][1]=1;
      len=strlen(s1+1);s1[len]--;
      for(int i=len;i>=1;i--)if(s1[i]<'0')s1[i]+=10,s1[i-1]--;else break;
      S=mul(S,T,s1,len);
      cout<<S.a[0][0]<<endl;
      return 0;
  }
  S.a[0][0]=a;S.a[1][0]=b;S.a[1][1]=1;
  T.a[0][0]=c;T.a[1][0]=d;T.a[1][1]=1;T.a[0][1]=0;

  len=strlen(s1+1);s1[len]-=2;
  for(int i=len;i>=1;i--)if(s1[i]<'0')s1[i]+=10,s1[i-1]--;else break;
  S=mul(S,S,s1,len);O=S;S=S*T;

  len=strlen(s2+1);s2[len]-=2;
  for(int i=len;i>=1;i--)if(s2[i]<'0')s2[i]+=10,s2[i-1]--;else break;
  S=mul(S,S,s2,len);

  T.a[0][0]=T.a[0][1]=1;T.a[1][0]=T.a[1][1]=0;
  S=T*S;S=S*O;
  cout<<S.a[0][0]<<endl;
  return 0;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8563970.html

时间: 2024-10-10 21:04:54

bzoj 3240: [Noi2013]矩阵游戏的相关文章

bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式: F[1][1]=1F[i,j]=a*F[i][j-1]+

BZOJ 3240 [Noi2013] 矩阵游戏 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24594825 [原题] 3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 336  Solved: 158 [Submit][Status] Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质

3240: [Noi2013]矩阵游戏

Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式: F[1][1]=1F[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

bzoj 1059: [ZJOI2007]矩阵游戏 二分图匹配

1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1891  Solved: 919[Submit][Status] Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种操作:行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵

bzoj 1059: [ZJOI2007]矩阵游戏 [二分图][二分图最大匹配]

Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N *N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种操作:行交换操作:选择 矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两列(即交换 对应格子的颜色)游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑 色.对于某些关卡,小Q百思不得其解,以致他开始怀疑这些关卡是不是根

BZOJ P1059 [ZJOI2007]矩阵游戏——solution

1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4604  Solved: 2211[Submit][Status][Discuss] Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N *N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种操作:行交换操作:选择 矩阵的任意两行,交换这两行(即交换对应格子的颜

【bzoj3240】 Noi2013—矩阵游戏

http://www.lydsy.com/JudgeOnline/problem.php?id=3240 (题目链接) 题意 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) 求解F[n][m],a,b,c,d为常数. Solution 原来费马小定理对于矩阵乘法同样适用..设a为一矩阵,p为质数则: 正好这里的模数1000000007为质数,那么把n,m模上(p-1)后进行矩阵快速幂即可.用来优化的矩阵很好构造,

BZOJ 1059 [ZJOI2007]矩阵游戏

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1059 题意:给定一个n * n的01矩阵,可以任意交换两行或两列的数字,问是否能调整出一个局面,使得矩阵的主对角线(左上角到右下角的连线)上都是1.n≤200. 题解: 由于每次可以变化一些元素为1的点的行号与列号,但是其相对位置是不变的,也就是说对于(i,j)的元素,经过变换之后是(ai,bj),{an}和{bn}是1-n的排列,所以我们可以抛弃这些点的行号与列号来分析他们的相对关系. 目

bzoj3240: [Noi2013]矩阵游戏

Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式: F[1][1]=1F[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