123&&灌溉

题目

小蓝发现了一个有趣的数列,这个数列的前几项如下:

1,1,2,1,2,3,1,2,3,4,⋯

小蓝发现,这个数列前 1项是整数1,接下来2 项是整数1 至2,接下来3 项是整数1 至3,接下来4 项是整数1 至 4,依次类推。

小蓝想知道,这个数列中,连续一段的和是多少。

思路

将每段连续的123都视为一行,即1121231234有4行,第n行有1-n个数。首先得到起点所在的行,算出从数列第一项到该起点的和,对终点也做同样操作,将终点的和-起点的和得到这段的和输出。

但这样只能通过4个测试用例,其他用例运行超时。

看了题解,发现求这种数列的和有个数学公式:1+1+2+1+2+3+,,,,+1+2+,,,+N=N(N+1)(N+2)/6

但是还是超时???不理解 (搞错了 发现自己二分法的代码没有删掉之前的暴力)通过7个,另外3个 答案错误???可能是精度问题?(果然,将上面公式写为//就ac了,比赛要注意一下这个问题!)

代码

import os
import sys

# 请在此输入您的代码
def find_row(a):
  # 使用二分法对该数所处行进行查找 最后返回l的值 即为该数所处行数
  #row = 1 最开始没删这个 我还疑惑为啥还是超时!
  #while((1 + row) * row / 2 < a):
    #row += 1
  r = 1000000000000
  l = 1
  while l <= r:
    mid = int((r + l)/2)
    if (1 + mid) * mid / 2 < a:
      l = mid + 1
    else:
      r = mid - 1
  return l

def get_sum_start(row, a):
  # 得到整个数列到起点的和[1,a)
  # 起点位于第row行 
  add = 0
  global sum_dict
  sum_dict = {}
  if row == 1: #因为range(1,1)是不会进入循环的 因此1作为单独的情况处理
    return 0
  temp = 1
  for i in range(2, row): #前n行(不包括row这一行)的和
    if i in sum_dict.keys(): #使用一个字典来记录之前计算过的某一行的和 减少重复计算
      add += sum_dict[i]
      temp += i
      continue
    temp +=  i
    add += temp
    sum_dict[i] = temp
  add += sum( x for x in range(1, a - int((row - 1) * row / 2))) + 1 #加的1就是第一行的1 a-int((row - 1) * row / 2)表示row这一行的和
  return add

def get_sum_end(row, a):
  # 大部分与get_sum_start同理
  add = 0
  if row == 1:
    return 1
  temp = 1
  for i in range(2, row): #前n行的和
    if i in sum_dict.keys():
      add += sum_dict[i]
      temp += i
      continue
    temp +=  i
    add += temp
    sum_dict[i] = temp
  add += sum( x for x in range(1, a + 1 - int((row - 1) * row / 2))) + 1 # [0,b+1) = [0,b]
  return add


global sum_dict
T = int(input())
result = []
for i in range(T):
  start, end = map(int, input().split())
  strat_row = find_row(start) #得到起点所处的行
  end_row = find_row(end) # 终点所处的行
  sum_start = get_sum_start(strat_row, start) #[1,a)的和
  sum_end = get_sum_end(end_row, end) #[1, b]的和
  result.append(sum_end - sum_start)

for i in result:
  print(int(i), end= "\n")
  
# import os
# import sys

# # 请在此输入您的代码
# def find_row(a):
#   # 使用二分法对该数所处行进行查找 最后返回l的值 即为该数所处行数
#   r = 1000000000000
#   l = 1
#   while l <= r:
#     mid = int((r + l)/2)
#     if (1 + mid) * mid / 2 < a:
#       l = mid + 1
#     else:
#       r = mid - 1
#   return l

# def get_sum_start(row, a):
#   # 得到整个数列到起点的和[1,a)
#   # 起点位于第row行 
#   add = 0
#   if row == 1: #因为range(1,1)是不会进入循环的 因此1作为单独的情况处理
#     return 0
#   add = int(((row-1)**3 + 3 * (row - 1)**2 + 2 * (row - 1)) //6)
#   b = a - int((row - 1) * row / 2)
#   add += int((b-1)*b/2)
#   return add

# def get_sum_end(row, a):
#   # 与get_sum_start同理
#   add = 0
#   if row == 1:
#     return 1
#   add = int(((row-1)**3 + 3 * (row - 1)**2 + 2 * (row - 1)) //6)
#   b = a + 1 - int((row - 1) * row / 2)#[1, b+1) = [1, b]
#   add += int((b-1)*b/2)
#   return add


# global sum_dict
# T = int(input())
# result = []
# for i in range(T):
#   start, end = map(int, input().split())
#   strat_row = find_row(start) #得到起点所处的行
#   end_row = find_row(end) # 终点所处的行
#   sum_start = get_sum_start(strat_row, start) #[1,a)的和
#   sum_end = get_sum_end(end_row, end) #[1, b]的和
#   result.append(sum_end - sum_start)

# for i in result:
#   print(int(i), end= "\n")

题目

小蓝负责花园的灌溉工作。

花园可以看成一个n 行m 列的方格图形。中间有一部分位置上安装有出水管。

小蓝可以控制一个按钮同时打开所有的出水管,打开时,有出水管的位置可以被认为已经灌溉好。

每经过一分钟,水就会向四面扩展一个方格,被扩展到的方格可以被认为已经灌溉好。即如果前一分钟某一个方格被灌溉好,则下一分钟它上下左右的四个方格也被灌溉好。

给定花园水管的位置,请问k 分钟后,有多少个方格被灌溉好?

思路

 深度遍历,对目前已灌溉方格的四邻居进行遍历,然后计数。

代码

import os
import sys

# 请在此输入您的代码
n, m = map(int, input().split())
t = int(input())
point = [[0 for i in range(m+1)] for i in range(n+1)] #用来存储某个方格是否被访问过 (m+1)(n+1)与题目中的下标对齐
location = []
for i in range(t):
  x, y = map(int, input().split())
  point[x][y] = 1
  location.append([x, y])
k = int(input())

def Check(x, y):
  if x >=0 and x<= n and y >=0 and y <= m and point[x][y] == 0: #边界检查以及是否被放翁检查
    return True
  else:
    return False

nums = t #最初灌溉数量=水龙头的数量
offsets = [[0, 1], [0, -1], [1, 0], [-1, 0]]
for i in range(k):
  temp = []
  while len(location) != 0:
    a, b = location.pop() #依次遍历目前已灌溉好的方格
    for off_x, off_y in offsets:
      now_x = a + off_x
      now_y = b + off_y
      if Check(now_x, now_y): #检查该方格是否合法
        nums += 1
        point[now_x][now_y] = 1
        temp.append([now_x, now_y])# 用于存储下一分钟的起点
  location = temp[:] 

print(nums)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值