题解:P9885 [ICPC2018 Qingdao R] Sequence and Sequence
not_clever_syl · · 题解
模拟赛搬了这个题,写一发题解纪念我成功补掉依托shi。
以下
首先根据递推式我们可得:
当
接下来是一种叫“分部求和法”的神秘技巧:
令
出现了
于是我们枚举
这时我们设
每次递归都可以把
用
关于维护
预处理时间复杂度很小,查询复杂度是
python 代码:
python跑得比C++还快拿了最优解(那个匿名用户不算)
f = [None]*5
F = [None]*5
f[0] = [1]
fc = [1]*80
for i in range(1,80):
fc[i] = fc[i-1]*i
def getf(f:list, x:int):
n = len(f)
if x < n and x>=0:
return f[x]
if n>=80:
print(n)
r = 0
m = 1
for i in range(n):
m = m*(x-i)
for i in range(n):
t = m//(x-i)*f[i]*(-1 if (n-i-1)%2==1 else 1)
r += t*(fc[n]//fc[i])*(fc[n]//fc[n-i-1])
return r//(fc[n]*fc[n])
def work2(f):
r = f.copy()
n = len(f)
r.append(getf(f,n))
r[0] = 0
for i in range(1,len(r)):
r[i] += r[i-1]
return r
def work1(f):
r = [None]*len(f)*2
for i in range(len(r)):
r[i] = getf(f,i*(i+1)//2-1)
return r
ans = [None]*5
B = 700
q = [None]*B
p = [None]*B
def init():
q[0] = 0
q[1] = 1
q[2] = 2
p[0] = 0
p[1] = p[2] = 1
idc = 2
c = 0
for i in range(3,B):
q[i] = q[i-1] + q[idc]
p[i] = idc
c += 1
if c == idc + 1:
idc += 1
c = 0
for i in range(5):
if i:
f[i] = work1(F[i-1])
F[i] = work2(f[i])
ans[i] = [None]*B
ans[i][0] = 0
for j in range(1,B):
ans[i][j] = ans[i][j-1] + getf(f[i],j)*q[p[j]]
def getp(n: int):
l = 1
r = n
while r-l>1:
mid = (l+r)>>1
if mid*(mid+3)<2*n:
l = mid
else:
r = mid
return r
def g(d:int, n:int):
if n<B:
return ans[d][n]
p = getp(n)
return getf(F[d],n)*g(0,p)-g(d+1,p)
init()
t=int(input())
for tc in range(t):
n=int(input())
print(g(0,n))