当前位置:   article > 正文

2024蓝桥杯每日一题(矩阵乘法)

2024蓝桥杯每日一题(矩阵乘法)

备战2024年蓝桥杯 -- 每日一题
Python大学A组

        试题一:斐波那契
        试题二:垒筛子
        试题三:斐波那契数列前n项和
        试题四:牛站


试题一:斐波那契

【题目描述】

        在斐波那契数列中,Fib0=0,Fib1=1,Fibn=Fibn−1+Fibn−2(n>1)给定整数 n,求Fibnmod10000。

【输入格式】

        输入包含不超过 100 组测试用例。

        每个测试用例占一行,包含一个整数 n。

        当输入用例 n=−1时,表示输入终止,且该用例无需处理。

【输出格式】

        每个测试用例输出一个整数表示结果。

        每个结果占一行。

【数据范围】

        0≤n≤2×109

【输入样例】

  1. 0
  2. 9
  3. 999999999
  4. 1000000000
  5. -1

【输出样例】

  1. 0
  2. 34
  3. 626
  4. 6875

【解题思路】

        【f2,f3】 = 【[0,1],[1,1]】*【f1,f2】,也就是【fn,fn-1】 = A^n【f0,f1】

【Python程序代码】

  1. def matrix_mul(A,B,MOD):
  2. res = [[0]*2 for _ in range(2)]
  3. for i in range(2):
  4. for j in range(2):
  5. for k in range(2):
  6. res[i][j] = (res[i][j] +A[i][k]*B[k][j])%MOD
  7. return res
  8. def fib(k):
  9. ans = [[0,1],[0,0]]
  10. mat = [[0, 1], [1, 1]]
  11. while k>0:
  12. if k&1==1:
  13. ans = matrix_mul(ans,mat,10000)
  14. k = k>>1
  15. mat = matrix_mul(mat,mat,10000)
  16. return ans[0][0]
  17. while True:
  18. n = int(input())
  19. if n==-1:break
  20. if n==0:print(0)
  21. elif n==1:print(1)
  22. else:
  23. print(fib(n))

试题二:垒筛子

【题目描述】

        赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥!我们先来规范一下骰子:1 的对面是 4,2 的对面是 5,3 的对面是 6。假设有 m 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。atm想计算一下有多少种不同的可能的垒骰子方式。两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。由于方案数可能过多,请输出模 109+7的结果。

【输入格式】

        第一行包含两个整数 n,m,分别表示骰子的数目和排斥的组数。

        接下来 m 行,每行两个整数 a,b,表示 a 和 b 数字不能紧贴在一起。

【输出格式】

        共一个数,表示答案模 109+7 的结果。

【数据范围】

        1≤n≤109
        1≤m≤361
        1≤a,b≤6

【输入样例】

  1. 2 1
  2. 1 2

【输出样例】

544

【解题思路】

        状态转移 f[i][j] = f[i - 1][k] * 4 ,肯定是会爆的,考虑如何变成矩阵乘法的形式。构建状态转移矩阵,A,当x,y不能放一块时置为0,能放一块时置为4.

【Python程序代码】

  1. n,m = map(int,input().split())
  2. a = [[4]*6 for i in range(6)]
  3. p = 10**9+7
  4. def get_op(x):
  5. if x<3:return x+3
  6. else:return x-3
  7. for i in range(m):
  8. x,y = map(int,input().split())
  9. x,y =x-1,y-1
  10. a[x][get_op(y)]=0
  11. a[y][get_op(x)]=0
  12. f = [[0]*6 for i in range(6)]
  13. f[0]=[4,4,4,4,4,4]
  14. k = n-1
  15. def matrix_mul(a,b):
  16. c = [[0]*6 for i in range(6)]
  17. for i in range(6):
  18. for j in range(6):
  19. for k in range(6):
  20. c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % p
  21. return c
  22. while k:
  23. if k&1:f = matrix_mul(f,a)
  24. a = matrix_mul(a,a)
  25. k>>=1
  26. res = 0
  27. for i in range(6):
  28. res = (res+f[0][i])%p
  29. print(res)

试题三:斐波那契前 n 项和

【题目描述】

【解题思路】

        构建状态转移矩阵 a = [[0,1,0],[1,1,1],[0,0,1]],F(f2,f3,s2) = a*F(f1,f2,s1) 

【Python程序代码】

  1. n,m = map(int,input().split())
  2. f = [[0]*3 for i in range(3)]
  3. f[0] = [1,1,1]
  4. a = [[0,1,0],[1,1,1],[0,0,1]]
  5. def matrix_mul(a,b):
  6. c = [[0]*3 for i in range(3)]
  7. for i in range(3):
  8. for j in range(3):
  9. for k in range(3):
  10. c[i][j] = (c[i][j]+a[i][k]*b[k][j])%m
  11. return c
  12. k = n-1
  13. while k:
  14. if k&1:f=matrix_mul(f,a)
  15. a = matrix_mul(a,a)
  16. k>>=1
  17. print(f[0][2])

试题四:牛站

【题目描述】

        给定一张由 T 条边构成的无向图,点的编号为 1∼1000 之间的整数。求从起点 S 到终点 E 恰好经过 N 条边(可以重复经过)的最短路。注意: 数据保证一定有解。

【输入格式】

        第 1 行:包含四个整数 N,T,S,E。

        第 2..T 行:每行包含三个整数,描述一条边的边长以及构成边的两个点的编号。

【输出格式】

        输出一个整数,表示最短路的长度。

【数据范围】

        2≤T≤100
        2≤N≤106

【输入数据】

  1. 2 6 6 4
  2. 11 4 6
  3. 4 4 8
  4. 8 4 9
  5. 6 6 8
  6. 2 6 9
  7. 3 8 9

【输出数据】

10

【解题思路】

        类Floyd算法+qmi,参考AcWing 345. 牛站矩阵做法详解(类Floyd算法) - AcWing

【Python代码】

  1. n,t,s,e = map(int,input().split())
  2. cnt = 0
  3. d = dict()
  4. d[s] = cnt; cnt+=1
  5. s = d[s]
  6. d[e] = cnt; cnt+=1
  7. e = d[e]
  8. g = [[0x3f3f3f3f]*(210) for _ in range(210)]
  9. for i in range(t):
  10. c,a,b = map(int,input().split())
  11. if a not in d:
  12. d[a]=cnt; cnt+=1
  13. if b not in d:
  14. d[b]=cnt; cnt+=1
  15. a,b = d[a],d[b]
  16. g[a][b]=g[b][a] = min(g[a][b],c)
  17. def work(a,b):
  18. temp = [[0x3f3f3f3f]*(cnt+5) for _ in range(cnt+5)]
  19. for i in range(cnt):
  20. for j in range(cnt):
  21. for k in range(cnt):
  22. temp[i][j] = min(temp[i][j],a[i][k]+b[k][j])
  23. return temp
  24. res = [[0x3f3f3f3f]*(cnt+5) for _ in range(cnt+5)]
  25. for i in range(cnt):res[i][i]=0
  26. while n:
  27. if n&1:
  28. res = work(res,g)
  29. g = work(g,g)
  30. n>>=1
  31. print(res[s][e])

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/476239
推荐阅读
相关标签
  

闽ICP备14008679号