具体而言,给定两个整数 a , b a,b a,b,保证 b ≠ 0 b\neq 0 b=0。莲子要实现这样一个函数 fun ( a , b ) \operatorname{fun}(a,b) fun(a,b) 来将 b b b 的符号转移到 a a a 上。
具体而言, fun ( a , b ) = sgn ( b ) × ∣ a ∣ \operatorname{fun}(a,b)=\operatorname{sgn}(b)\times |a| fun(a,b)=sgn(b)×∣a∣。其中, sgn ( b ) = { 1 b > 0 − 1 b < 0 \operatorname{sgn}(b)=\begin{cases}1&b>0\\-1&b<0\end{cases} sgn(b)={1−1b>0b<0
换而言之:
如果使用一个三维坐标系描述 fun ( a , b ) \operatorname{fun}(a,b) fun(a,b),则应当如下图所示:
你只需输出 fun ( a , b ) \operatorname{fun}(a,b) fun(a,b) 的值。
样例输入
-1 2
样例输出
1
样例输入
0 -4
样例输出
0
样例输入
-12345 -54321
样例输出
-12345
提示
对于全部数据,保证 a , b a,b a,b 在 32 32 32 位有符号整型范围内,并且 b ≠ 0 b \neq 0 b=0。
第一次打开传智杯的题目,又是给图又是描述的,看得出传智杯的题目风格很严谨,篇幅稍长。
A题打卡题,只要稍微熟悉一点语言就没问题,用abs()
绝对值函数可以省事很多
a,b=map(int,input().split(' '))
def sub(b):
if b>0:
return 1
else:return -1
def fun(a,b):
return abs(a)*sub(b)
print(fun(a,b))
相比看来,python代码似乎的却很简洁
题目背景的问题可以转化为如下描述:
给定两个长度分别为 n , m n,m n,m 的整数 a , b a,b a,b,计算它们的和。
但是要注意的是,这里的 a , b a,b a,b 采用了某种特殊的进制表示法。最终的结果也会采用该种表示法。具体而言,从低位往高位数起,第 i i i 位采用的是 i + 1 i+1 i+1 进制。换言之,相较于十进制下每一位的「逢 10 10 10 进 1 1 1」,该种进制下第 i i i 位是「逢 i + 1 i+1 i+1 进 1 1 1」。
下图所示,左边是十进制的竖式加法;右边是这种特殊进制的竖式加法。图中的红色加号表示上一位发生了进位。
样例输入
5 4
3 3 2 1 1
3 2 2 1
样例输出
4 2 1 1 0
样例输入
10 1
10 9 8 7 6 5 4 3 2 1
0
样例输出
10 9 8 7 6 5 4 3 2 1
提示
对于全部数据,保证 1 ≤ n , m ≤ 2 × 1 0 5 1\le n,m\le 2\times 10^5 1≤n,m≤2×105,从低位往高位数起有 a i ∈ [ 0 , i ] a_i\in[0,i] ai∈[0,i], b i ∈ [ 0 , i ] b_i\in[0,i] bi∈[0,i]。请使用 Java 或 Python 语言作答的选手注意输入输出时的效率。
读懂题目:
看着题目背景一开始被吓到了,那么长、又是进制题。但耐心读下来发现,其实就是解决一个随着位数增长、进制数也一起增长的特别的加法而已
输入数据预处理:
输入两个数组不等长,为方便加法,两个数组都在高位补零至等长,长度为两个数组中较长的数组长度+1,加一是因为在最高位做加法时也可能进位
核心加法部分:
抱着脑袋想一会儿,会发现进制数随数组位数改变,且这个改变是固定的,进制数=数组位数+2
再想一会儿,会发现每位做加法时,位的值=两个数的和%进制数
(取模),而加法在进位时,设进位的值为temp,那么temp=两个数的和//进制数
(整除)
丢分反思:
(1)没想到最高位进位时候的情况,导致一些数据集错误
(2)进位的值的逻辑差了一小点,导致做加法时有瑕疵,就差了这句:
temp = 0 #每次加法后进位值要初始化成0
n,m=map(int,input().split(' '))
a=list(map(int,input().split(' ')))
b=list(map(int,input().split(' ')))
a=a[::-1] #倒转数组
b=b[::-1]
sum=[]
ma_le=max(len(a),len(b))
mi_le=min(len(a),len(b))
#2.输入数据预处理:
#输入两个数组不等长,为方便加法,两个数组都在高位补零至等长,
#长度为两个数组中较长的数组长度+1,加一是因为在最高位做加法时也可能进位
for i in range(ma_le-mi_le+1):
if len(a)<len(b):
a.append(0)
else:b.append(0)
if len(a)<len(b):
a.append(0)
else:b.append(0)
# 核心加法部分
temp=0 #设进位的值为temp
for i in range(ma_le+1): #遍历 较长数组长度加一 次
ad=a[i]+b[i]+temp #每位两个数字加进位值的总和
temp = 0 #每次加法后进位值要初始化成0
if ad>=i+2: #发生进位
sum.append(ad%(i+2)) #位的值=两个数的和%进制数
temp=ad//(i+2) #进位值=两个数的和//进制数
elif ad<i+2: #不发生进位
sum.append(ad)
#最高位可能有0冗余,格式化后输出
sum=sum[::-1]
if len(sum)>1:
if sum[0]==0:
sum.remove(0)
# 输出格式
for i in sum:
print(i,end=' ')
市场每一天的贸易差可以视为一个有周期性规律的数列 a a a: [ 0 ] , [ 0 , 1 , 0 , − 1 , 0 ] , [ 0 , 1 , 2 , 1 , 0 , − 1 , − 2 , − 1 , 0 ] , [ 0 , 1 , 2 , 3 , 2 , 1 , 0 , − 1 , − 2 , − 3 , − 2 , − 1 , 0 ] … \color{red}[0],\color{blue}[0,\allowbreak 1,\allowbreak 0,\allowbreak -1,\allowbreak 0],\color{red}[0,\allowbreak 1,\allowbreak 2,\allowbreak 1,\allowbreak 0,\allowbreak -1,\allowbreak -2,\allowbreak -1,\allowbreak 0],\allowbreak \color{blue}[0,\allowbreak 1,\allowbreak 2,\allowbreak 3,\allowbreak 2,\allowbreak 1,\allowbreak 0,\allowbreak -1,\allowbreak -2,\allowbreak -3,\allowbreak -2,\allowbreak -1,\allowbreak 0]\dots [0],[0,1,0,−1,0],[0,1,2,1,0,−1,−2,−1,0],[0,1,2,3,2,1,0,−1,−2,−3,−2,−1,0]… 具体而言, a a a 可以被分为无穷段,第 i i i 段的内容为 { 0 , 1 , ⋯ , i , i − 1 , ⋯ , 0 , − 1 , ⋯ , − i , − i + 1 , ⋯ 0 } \{0,\allowbreak 1,\allowbreak \cdots,\allowbreak i,\allowbreak i-1,\allowbreak \cdots,0,\allowbreak -1,\allowbreak \cdots,\allowbreak -i,\allowbreak -i+1,\allowbreak \cdots 0\} {0,1,⋯,i,i−1,⋯,0,−1,⋯,−i,−i+1,⋯0}。如下图所示,是将 a a a 数列内的前一些点绘制在坐标轴上的情况:
现在梅莉对市场发起了 q q q 次询问,每次她会给定一个 k k k,希望求出 a k a_k ak 是多少。
样例输入
9
1
10
100
1000
10000
100000
1000000
10000000
100000000
样例输出
0
1
6
-9
-11
-128
406
1629
5154
提示
对于所有数据, 1 ≤ q ≤ 1 0 5 1 \leq q \leq 10^5 1≤q≤105, 1 ≤ k ≤ 4 × 1 0 18 1 \leq k \leq 4\times 10^{18} 1≤k≤4×1018。
0=2top^2+3*top+1-x
,这个方程的对称轴为-3/4,开口向上,定义域为0到正无穷,所以,对这个方程使用求根公式并向上取整就能得出此时X所在波形的top:top= ceil((-3 + sqrt(1 + 8 * x)) / 4) #每个波形的顶点值
last_dot = top + 2 * (top - 1) * ((top - 1) + 1)
,以此就能计算此时X在此波形中的相对位置rel_dot = x - last_dot - 1
if 0 <= rel_dot < top: #分段函数
return rel_dot
elif top <= rel_dot < 3 * top:
return -rel_dot + 2 * top
elif 3 * top <= rel_dot <= 4 * top:
return rel_dot - 4 * top
比赛的时候我就是在分段函数上写错了一点,满盘皆输!!
from math import ceil, sqrt
# import numpy as np
# from matplotlib import pyplot as plt
def fun(x):
top= ceil((-3 + sqrt(1 + 8 * x)) / 4) #每个波形的顶点值
last_dot = top + 2 * (top - 1) * ((top - 1) + 1) #上一个波形的结束点
rel_dot = x - last_dot - 1 #在此波形中的相对位置
if 0 <= rel_dot < top: #分段函数
return rel_dot
elif top <= rel_dot < 3 * top:
return -rel_dot + 2 * top
elif 3 * top <= rel_dot <= 4 * top:
return rel_dot - 4 * top
q=int(input())
for i in range(q):
print(fun(int(input())))
# x=np.linspace(0,30, 1000)
# y = np.array([fun(each) for each in x]) #根据x计算各点函数值
# plt.figure()
# plt.plot(x, y)
# plt.ylim(-5,5) #限制y的范围
# plt.xlim(0,30) #限制x的范围
# plt.show()
待续…✌️