题解:蓝桥云课 3075 特殊的多边形
【题目来源】
蓝桥云课:1.特殊的多边形 - 蓝桥云课 (lanqiao.cn)
【题目描述】
假设一个 \(n\) 边形 \(n\) 条边为 \(a_1,a_2,a_3,…,a_n\),定义该 \(n\) 边形的值 \(v=a_1×a_2×a_3×...×a_n\)。
定义两个 \(n\) 边形不同是指至少有一条边的长度在一个 \(n\) 边形中有使用而另一个 \(n\) 边形没有用到,如 \(n\) 边形 \((3,4,5,6)\) 和 \((3,5,4,6)\) 是两个相同的 \(n\) 边形,\((3,4,5,6)\) 和 \((4,5,6,7)\) 是两个不相同的 \(n\) 边形。
现在有 \(t\) 和 \(n\),表示 \(t\) 个询问并且询问的是 \(n\) 边形,每个询问给定一个区间 \([l,r]\),问有多少个 \(n\) 边形(要求该 \(n\) 边形自己的 \(n\) 条边的长度互不相同)的值在该区间范围内。
【输入】
第一行包含两个正整数 \(t\)、\(n\),表示有 \(t\) 个询问,询问的是 \(n\) 边形。
接下来 \(t\) 行,每行有两个空格隔开的正整数 \(l\)、\(r\),表示询问区间\([l,r]\)。
【输出】
输出共 \(t\) 行,第 \(i\) 行对应第 \(i\) 个查询的 \(n\) 边形个数。
【输入样例】
4 3
1 10
30 50
60 200
200 400
【输出样例】
0
1
18
32
【算法标签】
《蓝桥云课 3008 特殊的多边形》 #前缀和# #搜索# #DFS#
【代码详解】
#利用DFS求所有的N边形,边长乘积不超过100000
#N边形:最小的N-1条边之和>第N边,即tot - path[-1] > pathp[-1]
def dfs(depth, last_val, tot, mul):
"""
depth: 第几条边
last_val: 上一条边的边长
tot: 当前所有边长之和
mul: 当前所有边长之积
"""
if depth == n:
#N边形的条件
if tot > 2 * path[-1]:
#此时是一个合法的N边形
ans[mul] += 1
return
#枚举第depth条边的边长为i
for i in range(last_val + 1, 100000):
#最优性剪枝:要保证乘积不超过100000
#先前选择了depth个数字,乘积为mul
#后续还有n-depth个数字,每个数字都要>i
if mul * (i**(n-depth)) <= 100000:
path.append(i)
dfs(depth+1, i, tot+i, mul*i)
path.pop()
else:
break
#ans[i]表示价值为i的N边形数目
ans = [0] * 1000001
t, n = map(int, input().split())
path = []
dfs(0, 0, 0, 1)
#每次询问一个区间l, r,输出有多少个N边形的价值在[l,r]中
#等价于ans[l]+...ans[r],所以需要对ans求前缀和
for i in range(100001):
ans[i] += ans[i-1]
for _ in range(t):
l, r = map(int, input().split())
print(ans[r]-ans[l-1])
【运行结果】
4 3
1 10
30 50
60 200
200 400
0
1
18
32
浙公网安备 33010602011771号