蓝桥杯备赛(八)-数论

蓝桥杯备赛(八)-数论

概念

通过引入质数筛、最大公约数、mod的性质、ex_gcd来作为蓝桥基础数论算法。

实例

Q1

等差数列(原题链接)

A1

本质寻求最大公差,需要注意为0的时候!!!特殊用例。
代码如下:

def gcd(a,b):
    if b==0:
        return a
    c=a%b 
    if c!=0:
        return gcd(b,c)
    return b
n=int(input())
lst=list(map(int,input().split()))
lst.sort()
q_lst=[]
for i in range(1,n):
    q_lst.append(lst[i]-lst[0])
d=gcd(q_lst[1],q_lst[0])
if d==0:
    print(n)
else:
    for i in range(2,n-1):
        d=gcd(d,q_lst[i])
    print((lst[-1]-lst[0])//d+1)

Q2

X的因子链(原题链接)

A1

需要用到质数筛,然后运用到一个数学基本定理:任何一个数可以由质数的乘积构成。于是这里就知道了该怎么引入因子链了吧。
代码如下:

def get_primes(n):
    primes=[0 for _ in range(n+1)]
    min_p=[0 for _ in range(n+1)]
    st=[0 for _ in range(n+1)]
    cnt=0
    for i in range(2,n):
        if not st[i]:
            min_p[i]=i
            primes[cnt]=i
            cnt+=1
        for j in range(cnt):
            t=i*primes[j]
            if t>n:
                break
            st[t]=1
            min_p[t]=primes[j]
            if i%primes[j]==0:
                break
    return primes,min_p,cnt
def fac(num):
    res=1
    for i in range(2,num+1):
        res*=i
    return res
if __name__=="__main__":
    primes,min_p,_=get_primes(2000000)
    while True:
        try:
            x=int(input())
            pri=[0]*30
            cnt2=[0]*30
            k=0
            while x>1:
                pri[k]=min_p[x]
                while x%pri[k]==0:
                    cnt2[k]+=1
                    x//=pri[k]
                k+=1
            tot=sum(cnt2)
            times=fac(tot)
            for i in range(k):
                times//=fac(cnt2[i])
            print(tot,times)
        except:
            break

Q3

聪明的燕姿(原题链接)

A3

难的想死,dfs+数论,自己看着办吧。dfs需要三个参数。
代码如下:

N=100000
st=[0 for _ in range(N+1)]
prime=[0 for _ in range(N+1)]
res=[]
cnt=0
def get_prime():
    global cnt
    for i in range(2,N+1):
        if not st[i]:
            prime[cnt]=i
            cnt+=1
        for j in range(cnt):
            t=prime[j]*i
            if t>N:
                break
            st[t]=1
            if i%prime[j]==0:
                break

def is_prime(n):
    if n<=N:return not st[n]
    for i in range(cnt):
        if prime[i]*prime[i]>n:
            break
        if n%prime[i]==0:
            return False
    return True

def dfs(last,product,s):
    if s==1:
        res.append(product)
        return 
    if last<0:
        num=0
    else:
        num=prime[last]
    #特判一次
    if s-1>num and is_prime(s-1):
        res.append(product*(s-1))
    i=last+1
    while prime[i]<=s/prime[i] and i <cnt:
        p=prime[i]
        j=1+p
        t=p
        while j<=s:
            if s%j==0:
                dfs(i,product*t,s//j)
            t*=p
            j+=t
        i+=1
get_prime()
while True:
    try:
        n=int(input())
        dfs(-1,1,n)
        print(len(res))
        if len(res):
            print(' '.join(list(map(str,sorted(res)))))
        res=[]
    except:
        break

Q4

五指山(原题链接)

A4

拓展欧几里得算法的运用。以及对于如何取最小正数的处理。
代码如下:

def exgcd(a,b):
    global x,y
    if b==0:
        x,y=1,0
        return a
    else:
        d=exgcd(b,a%b)
        #这里是求下一层的,所以要递归上去的画,就得用减号
        x_=y
        y_=x-(a//b)*y
        x=x_
        y=y_
        return d
#记住上面的算法,是有很大的学问的
for _ in range(int(input())):
    n,d,a,b=map(int,input().split())
    x,y=0,0
    gcd=exgcd(n,d)
    if not (b-a)%gcd:
        y*=(b-a)//gcd
        n//=gcd
        print((y%n+n)%n)
    else:
        print('Impossible')

Q5

最大比例(原题链接)

A5

需要用到辗转相减。分子分母分离求。
代码如下:

#1223.最大比例
def gcd(a,b):
    if b==0:
        return a 
    c=a%b
    if c==0:
        return b
    return gcd(b,c)
#辗转相减法
def sub_gcd(a,b):
    if a>b:
        t=a
        a=b
        b=t
    if a==1:
        return b
    return sub_gcd(a,b//a)
n=int(input())
lst=list(set(sorted(list(map(int,input().split())))))
a=[]#存放分子
b=[]#存放分母
for i in range(1,len(lst)):
    d=gcd(lst[i],lst[0])
    a.append(lst[i]//d)
    b.append(lst[0]//d)
up,down=a[0],b[0]
for i in range(1,len(a)):
    up=sub_gcd(up,a[i])
    down=sub_gcd(down,b[i])
print('{}/{}'.format(up,down))

Q6

糖果(原题链接)

A6

需要注意的是,这题利用状态压缩DP很快就能做出来。
代码如下:

n,m,k=map(int,input().split())
dp=[-1 for _ in range(1<<20)]#表示口味为v时所需要的最少糖果包数
st_lst=[]
tot=(1<<m)-1
for i in range(n):
    st=0
    lst=list(map(int,input().split()))
    for j in range(k):
        st|=(1<<lst[j]-1)#注意<<的优先级低于基础运算符号
    dp[st]=1
    st_lst.append(st)

for i in range(tot+1):
    if dp[i]!=-1:
        for j in range(n):
            st=st_lst[j]
            if dp[i|st]==-1 or dp[i|st]>dp[i]+1:
                dp[i|st]=dp[i]+1
print(dp[tot])

Q7

C循环(原题链接)

A7

ex_gcd
代码如下:

def ex_gcd(a,b):
    global x,y
    if b==0:
        x,y=1,0
        return a
    else:
        d=ex_gcd(b,a%b)
        x_=y
        y_=x-(a//b)*y
        x=x_
        y=y_
    return d

while True:
    A,B,C,k=map(int,input().split())
    if A==0 and B==0 and C==0 and k==0:
        break
    x,y=0,0
    d=ex_gcd(C,1<<k)
    if (B-A)%d==0:
        x*=(B-A)//d
        n=(1<<k)//d
        print((x%n+n)%n)
    else:
        print('FOREVER')

Q8

正则问题(原题链接)

A8

主要在于如何构建递归搜索树,也就是我们的dfs。
代码如下:

def dfs():
    global k
    res=0
    while k<len(str_):
        if str_[k]=='(':
            k+=1
            res+=dfs()#进入下一层递归
            k+=1#跳过)
        elif str_[k]=='|':
            k+=1
            res=max(res,dfs())
        elif str_[k]=='x':
            res+=1
            k+=1
        elif str_[k]==')':
            break
        else:
            break
    return res
k=0
str_=input()
print(dfs())

总结

(xx.xx)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值