目录
1.快速幂模板
题目描述
输入 b,p,k 的值,求 b^p \mod k的值。其中 b,p,k 为 int64 数。
输入描述
三个整数 b,p,k。
输入描述
输出 b^p \mod k=s,s 为运算结果。
样例输入
2 10
样例输出
7
def fastPow(a,n,mod):
ret = 1
while n:
if(n&1):
ret = ret*a % mod
a = a*a % mod
n>>=1
return ret
a,n,p = map(int, input().split())
print(fastPow(a,n,p))
2.RSA解密 2019年省赛
题目描述
RSA 是一种经典的加密算法。它的基本加密过程如下。
首先生成两个质数 p,q,令 n=p⋅q,设 d 与 (p−1)⋅(q−1) 互质,则可找到 e 使得 d⋅e 除 (p−1)⋅(q−1) 的余数为 1。
n,d,e 组成了私钥,n,d 组成了公钥。
当使用公钥加密一个整数 X 时(小于 n),计算 ,则 C 是加密后的密文。
当收到密文 C 时,可使用私钥解开,计算公式为
例如,当 p = 5, q = 11, d = 3时,n = 55 e = 27。
若加密数字 24,得 解密数字 19,得
现在你知道公钥中 n = 1001733993063167141, d = 212353,同时你截获了别人发送的密文 C = 20190324,请问,原文是多少?
1.求p,q
因为p,q是质数,所以n只有这两个因子
from math import *
n = 1001733993063167141
k = int(sqrt(n))
for i in range(2,k):
if n%i == 0:
print(i,n//i)
p=891234941、q=1123984201。
2.求e
d*e/(p-1)*(q-1)=k·····1
n = 1001733993063167141
d = 212353
p=891234941
q=1123984201
tmp = (p - 1) * (q - 1)
print(tmp)
for i in range(2,n+1):
now = i * tmp + 1
if (now % d == 0):
print(now // d) #打印e
break #有很多e,求第一个就行了
3.求
def fastPow(a,b,mod):
ret = 1
while b:
if(b&1):
ret = ret*a % mod
a = a*a % mod
b>>=1
return ret
n = 1001733993063167141
e = 823816093931522017 #试试其他的e
C = 20190324
print(fastPow(C,e,n)) #579706994112328949
3.矩阵相乘
题目描述
小明最近刚刚学习了矩阵乘法,但是他计算的速度太慢,于是他希望你能帮他写一个矩阵乘法的运算器。
输入描述
输入的第一行包含三个正整数 N,M,K,表示一个 $NM的矩阵乘以一个的矩阵乘以一个MK$ 的矩阵。
接下来 N 行,每行 M 个整数,表示第一个矩阵。再接下来的 M 行,每行 K 个整数,表示第二个矩阵。
0<N,M,K≤100, 0≤ 矩阵中的每个数≤1000。
输入描述
输出有 N 行,每行 K 个整数,表示矩阵乘法的结果。
样例输入
2 1 3 1 2 1 2 3
样例输出
1 2 3 2 4 6
A=[]
B=[]
C=[[0 for i in range(101)]for j in range(101)]
n,m,a=map(int,input().split())
for i in range(n):
A.append(list(map(int,input().split())))
for j in range(m):
B.append(list(map(int,input().split())))
for i in range(n):
for j in range(a):
for k in range(m):
C[i][j]+=A[i][k]*B[k][j]
for i in range(n):
for j in range(a):
print(C[i][j],end=' ')
print()
4.矩阵快速幂
题目描述
给定一个 N 阶矩阵 A 和一个常数 M,请你输出 A 的 M 次幂。
输入描述
输入第一行包含两个整数 N,M。
接下来 N 行,每行包含 N 个数,表示矩阵 A。
1≤N≤30,0≤M≤5,0≤ 矩阵中的每个数 ≤5。
输入描述
输出有 N 行,每行 N 个整数,表示 。
样例输入
2 2 1 2 3 4
样例输出
7 10 15 22
def multi(A,B):
n=len(A)
C=[[0 for i in range(n)]for j in range(n)]
for i in range(n):
for k in range(n):
for j in range(n):
C[i][j]+=A[i][k]*B[k][j]
return C
def power(A, n):
N = len(A)
res = [[0] * N for i in range(N)]
for i in range(N):
res[i][i] = 1
while n:
if n &1:
res = multi(res, A)
A = multi(A, A)
n>>= 1
return res
n,m=map(int,input().split())
A=[]
for i in range(n):
A.append(list(map(int,input().split())))
li=power(A,m)
for i in range(n):
for j in range(n):
print(li[i][j],end=' ')
print()
5.垒骰子 2015年省赛
题目描述
赌圣 atm 晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。
经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥!
我们先来规范一下骰子:1 的对面是 4,2 的对面是 5,3 的对面是 6。
假设有 m 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。
atm 想计算一下有多少种不同的可能的垒骰子方式。
两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。
由于方案数可能过多,请输出模 的结果。
不要小看了 atm 的骰子数量哦~
输入描述
输入第一行两个整数 n,m,n 表示骰子数目;
接下来 m 行,每行两个整数 a,b ,表示 a 和 b 数字不能紧贴在一起。
其中,
输入描述
输出一行一个数,表示答案模 的结果。
样例输入
2 1 1 2
样例输出
544
我们先不考虑互斥问题,推理一下有多少种方案:
- 1个骰子的情况。一个骰子有 6 个面,每个面朝上的时候侧面都可以旋转得到 4 个不同的摆放结果,共有 4×6=24 种。
- 2 个骰子的情况。一上一下两个骰子,共有(4×6)×(4×6)=576 种
-
1 个骰子的 6 个面的总方案= 6 个面,每个面 4 种方案,共 4×6=24 种。
-
从 1 个骰子到 2 个骰子,乘以一个转移矩阵:
垒 2 个骰子的方案 = ,共 (4×6) × (4×6)=576种。
-
垒 3 个骰子的方案 ==
-
⋯
大佬:这样就转换成了矩阵乘法。垒 n 个骰子,等于 n−1 个转移矩阵相乘,最后再乘以第 1 个骰子。不过如果加上互斥,就需要排除一些情况,即把转移矩阵中互斥的位置置为 0。
import math
mod = int(math.pow(10,9))+7
def multi(A, B): #矩阵乘法
C = [[0]*6 for i in range(6)]
for i in range(6):
for j in range(6):
for k in range(6):
C[i][j] = int((C[i][j] + A[i][k] * B[k][j]) % mod)
return C
def power(A, n): #矩阵快速幂
res = [[0]*6 for i in range(6)]
for i in range(6):
res[i][i] = 1
while n:
if n % 2:
res = multi(res, A)
A = multi(A, A)
n >>= 1
return res
def solve(n, dice):
transfer = [[4]*6 for i in range(6)] #转移矩阵
for i in range(6): #去掉互斥的情况
for j in dice.get((i+3)%6,[]): #0对面是3,1对4,2对5
transfer[i][j]= 0
transfer = power(transfer, n-1) #转移矩阵乘n-1次
temp = [4]*6 #表示最下面的骰子
ans = [0]*6
for i in range(6): #最后乘最下面的骰子
for j in range(6):
ans[i] += transfer[i][j] * temp[j]
print(int(sum(ans) % mod))
n, m = [int(str) for str in input().split()]
dice = dict() #用字典记录互相排斥的面
for i in range(m):
x, y = [int(str)-1 for str in input().split()]
if x not in dice: dice[x] = [y]
else: dice[x].append(y)
if y not in dice: dice[y] = [x]
else: dice[y].append(x)
solve(n, dice)