首页 > 编程语言 >《Lua程序设计第四版》 第三部分22~25章自做练习题答案

《Lua程序设计第四版》 第三部分22~25章自做练习题答案

时间:2023-08-20 17:35:24浏览次数:70  
标签:练习题 25 end 22 -- print return function local

Lua程序设计第四版第三部分编程实操自做练习题答案,带⭐为重点。

22.1

本章开始时定义的函数getfield,由于可以接收像math?sin或string!!!gsub这样的字段而不够严谨。请将其进行重写,使得该函数只能支持点作为名称分隔符。

function getfield(f)
    if string.find(f, "[^%w%._]") then
        error("not '.' sep", 2)
    end
    local G = _G
    for v in string.gmatch(f, "[%a_][%w_]*") do
        G = G[v]
    end
    return G
end

read = getfield("io.read")
print(read)
sin = getfield("math?sin")
gsub = getfield("string!!!gsub")

22.2 ⭐

请解释下列程序做了什么,以及输出结果是什么

local foo -- 声明局部变量foo
do
    local _ENV = _ENV -- 在do...end范围内生效的新环境,内部环境=外部环境
    function foo() -- 局部变量foo被赋值了函数
        print(X) -- 内部_ENV.X,也是外部_ENV.X
    end
end
X = 13 -- 外部ENV.X 改为 13
_ENV = nil -- 外部_ENV变为nil
foo() -- 调用了局部变量foo函数,打印内部_ENV.X,因为内部_ENV依旧引用着原先的外部_ENV表,所以打印13
X = 0 -- 修改外部_ENV.X 因为外部ENV此时为nil,故发生错误

-- 13
-- 22.2.lua:11: attempt to index a nil value (upvalue '_ENV')

22.3 ⭐

请详细解释下列程序做了什么,以及输出的结果是什么

local print = print -- 局部变量print赋值了_ENV.print
function foo(_ENV, a) -- _ENV.foo 被赋值了函数,函数体根据传入的_ENV环境参数执行
    print(a + b) -- a是函数定义里的形参,b是传入环境 _ENV.b
end

foo({ -- 调用 _ENV.foo
    b = 14 -- 传入了一个新环境
}, 12)
foo({
    b = 10 -- 传入了一个新环境
}, 1)

-- 26
-- 11

23.1 ⭐

请编写一个实验证明为什么Lua语言需要实现瞬表(记得调用函数collectgarbage来强制进行一次垃圾收集)

一个具有弱引用键和强引用值的表叫瞬表

collectgarbage() -- 清理之前dofile占用的内存空间
n = collectgarbage("count") * 1024
print(n)
local memory = {}
for i = 1, 2 ^ 10, 1 do
    local t = {i}
    memory[t] = function()
        t[1] = t[1] + 1 -- 间接引用了键
        return t
    end
end
-- 假如没有瞬表
collectgarbage()
n = collectgarbage("count") * 1024
print(n)
-- 假如有瞬表了
mt = {}
mt.__mode = "k"
setmetatable(memory, mt)
collectgarbage()
n = collectgarbage("count") * 1024
print(n)
-- 再清空 memory
memory = nil
collectgarbage()
n = collectgarbage("count") * 1024
print(n)

23.2

书上23.6节的第一个示例创建了一个带有析构器的表,该析构器在执行时只是输出一条消息。如果程序没有进行过垃圾收集就退出会发生什么?如果程序调用了os.exit呢?如果程序由于出错而退出呢?

o = {
    x = "hi"
}
setmetatable(o, {
    __gc = function(o)
        print(o.x)
    end
})
o = nil
-- error("123", 123)
-- os.exit()
collectgarbage()
  • 如果一个对象直到程序运行结束后还没有被回收,那么Lua语言就会在整个Lua虚拟机关闭后调用它的析构器
  • 调用os.exit() 不会调用未回收对象的析构器,直接退出了程序
  • 因为出错而退出程序,会在退出时调用未回收对象的析构器

23.3 ⭐

假设要实现一个记忆表,该记忆表所针对函数的参数和返回值都是字符串。由于弱引用表不把字符串当做可回收对象,因此将这个记忆表标记为弱引用并不能使得其中的键值对能够被垃圾收集。在这种情况下,你该如何实现记忆呢?

给字符串值套上一层表,变成只有一个元素的序列对象

memory = {}
setmetatable(memory, {
    __mode = "v",
    __len = function(t)
        local count = 0
        for k, v in pairs(t) do
            count = count + 1
        end
        return count
    end
})
collectgarbage()

function myMemory(k, v)
    local tmp = memory[k]
    if tmp == nil then
        memory[k] = {v or k}
    end
    return memory[k][1]
end

myMemory("a", "a")
myMemory("b", "b")
myMemory("c", "c")
v = myMemory "b"
print(v)
print(#memory)
collectgarbage()
print(#memory)

23.4 ⭐

解释示例的程序的输出

local count = 0

local mt = {
    __gc = function()
        count = count - 1
    end
}
local a = {}

for i = 1, 10000 do
    count = count + 1
    a[i] = setmetatable({}, mt)
end

collectgarbage()
print(collectgarbage("count") * 1024, count) -- 多出来的内存,10000
a = nil
collectgarbage()
print(collectgarbage("count") * 1024, count) -- 删除键的对象内存,执行值的对象的析构方法,0
collectgarbage()
print(collectgarbage("count") * 1024, count) -- 删除已被析构的值的对象内存,0
--[[
844706.0        10000
582570.0        0
22570.0 0
--]]

23.5

你需要至少一个使用很多内存的Lua脚本

  • 使用不同的pause和stepmul运行脚本。看看对性能的影响
  • 调整脚本,使其能够完整地控制垃圾收集器。脚本应该让垃圾收集器停止运行,然后时不时地完成垃圾收集工作。
-- collectgarbage("setpause", 0)
-- collectgarbage("setpause", 1000)
-- collectgarbage("setstepmul", 1)
-- collectgarbage("setstepmul", 1000000)
start = os.clock()
local a = {}
setmetatable(a, {
    __mode = "v"
})
collectgarbage("stop")
for i = 1, 2 ^ 26, 1 do
    a[i] = {}
    if i % 2 ^ 12 == 0 then -- or use os.time
        collectgarbage()
    end
end
print(os.clock() - start)
--[[
默认 3.723
pause=0  4.404
pause=1000  3.571
stepmul=1 4.85
stepmul=1000000 3.972

默认+i % 2 ^ 13 == 0 4.385
自定义 4.559

--]]

协程传递值 ⭐

function consumer()
    while true do
        print(coroutine.yield())
    end
end

consumer = coroutine.create(consumer)

coroutine.resume(consumer, 1) -- 第一次唤醒,为consumer传入形参,运行到yield阻塞并返回,等待一个对resume的再次调用
coroutine.resume(consumer, 2) -- 第二次唤醒,yield函数结束,返回第二次resume调用的值
coroutine.resume(consumer, 3)

--[[
  2
  3
]]

协程全排列

function permgen(a, n)
    n = n or #a
    if n <= 1 then -- 迭代终止条件(全排列的某一种结果)
        -- printResult(a)
        coroutine.yield(a)
    else
        for i = 1, n, 1 do
            a[i], a[n] = a[n], a[i]
            permgen(a, n - 1)
            a[i], a[n] = a[n], a[i]
        end
    end
end

function printResult(a)
    for i = 1, #a do
        io.write(a[i], " ")
    end
    io.write("\n")
end

function permutations1(a)
    local thread = coroutine.create(function() -- 需要一个函数而不是一个函数的调用
        permgen(a)  -- 闭包
    end)
    return function()
        local code, res = coroutine.resume(thread)
        return res
    end
end

function permutations2(a)
    local thread = coroutine.create(permgen)
    return function()
        local code, res = coroutine.resume(thread, a) -- 第一次唤醒协程传入参数a,闭包
        return res
    end
end

function permutations3(a)
    return coroutine.wrap(function()
        permgen(a)
    end)
end

for v in permutations1({1, 2, 3}) do
    printResult(v)
end

for v in permutations2({1, 2, 3}) do
    printResult(v)
end

for v in permutations3({1, 2, 3}) do
    printResult(v)
end

24.1

使用生产者驱动式设计重写生产者-消费者的示例,其中消费者是协程,而生产者是主线程

io.input("test.txt")

function producer()
    while true do
        local x = io.read(1)
        if not x then
            return
        end
        send(x)
    end
end

function consumer(x)
    while true do
        io.write(x, "\n")
        x = receive()
    end
end

consumer = coroutine.create(consumer)

function send(x)
    coroutine.resume(consumer, x)
end

function receive()
    return coroutine.yield()
end

producer()

24.2 ⭐

练习6.5要求编写一个函数来输出指定数组元素的所有组合。请使用协程把该函数修改为组合的生成器。该生成器的用法如下

for c in combinations({"a","b","c"}, 2) do
   printResult(c)
end
-- ^ 递归里不要对传入的实参做手脚,即函数形参t
function comb(list, n, res, index)
    res = res or {}
    index = index or 1
    if #res == n then
        -- io.write "{"
        -- io.write(table.concat(res, ","))
        -- io.write "}\n"
        coroutine.yield(res)
        return
    end
    if n - #res > #list or index > #list then
        return
    end
    -- 选择第index个
    res[#res + 1] = list[index]
    comb(list, n, res, index + 1)
    res[#res] = nil
    -- 不选第index个
    comb(list, n, res, index + 1)
end

function combinations(list, n)
    c = coroutine.wrap(comb)
    return function(s, c)
        return c(list, n)
    end, nil, nil
end

for c in combinations({1, 2, 3}, 2) do
    io.write "{"
    io.write(table.concat(c, ","))
    io.write "}\n"
end

24.3

在示例24.5中,函数getline和putline每一次调用都会产生一个新的闭包。请使用记忆机制来避免这种资源浪费。

local lib = require 'async-lib'

function run(code)
    local co = coroutine.wrap(function()
        code()
        lib.stop()
    end)
    co()
    lib.runloop()
end

local putlineMemory = {}
function putline(stream, line)
    local co = coroutine.running()
    local callback = putlineMemory[co]
    if not callback then
        callback = (function()
            coroutine.resume(co)
        end)
        putlineMemory[co] = callback
    end
    lib.writeline(stream, line, callback)
    coroutine.yield()
end

local getlineMemory = {}
function getline(stream, line)
    local co = coroutine.running()
    local callback = getlineMemory[co]
    if not callback then
        callback = (function(l)
            coroutine.resume(co, l)
        end)
        getlineMemory[co] = callback
    end
    lib.readline(stream, callback)
    local line = coroutine.yield()
    return line
end

run(function()
    local t = {}
    local inp = io.input("test.js")
    local out = io.output()

    while true do
        local line = getline(inp)
        if not line then
            break
        end
        t[#t + 1] = line
    end
    for i = #t, 1, -1 do
        putline(out, t[i] .. "\n")
    end
end)

24.4

请为基于协程的库(示例24.5)编写一个行迭代器,以便于使用for循环来读取一个文件

local lib = require 'async-lib'

function run(code)
    local co = coroutine.wrap(function()
        code()
        lib.stop()
    end)
    co()
    lib.runloop()
end

local putlineMemory = {}
function putline(stream, line)
    local co = coroutine.running()
    local callback = putlineMemory[co]
    if not callback then
        callback = (function()
            coroutine.resume(co)
        end)
        putlineMemory[co] = callback
    end
    lib.writeline(stream, line, callback)
    coroutine.yield()
end

local getlineMemory = {}
function getline(stream, line)
    local co = coroutine.running()
    local callback = getlineMemory[co]
    if not callback then
        callback = (function(l)
            coroutine.resume(co, l)
        end)
        getlineMemory[co] = callback
    end

    return function()
        lib.readline(stream, callback)
        local line = coroutine.yield()
        return line
    end, nil, nil
end

run(function()
    local t = {}
    local inp = io.input("test.js")
    local out = io.output()

    for line in getline(inp) do
        t[#t + 1] = line
    end

    for i = #t, 1, -1 do
        putline(out, t[i] .. "\n")
    end
end)

24.6 ⭐ ⭐

用Lua实现一个transfer函数。如果你觉得唤醒-挂起和调用-返回类似,那么transfer就类似goto:它会挂起当前运行的协程

然后唤醒其他作为参数的协程(提示:使用某种调度机制来控制协程。这样的话,transfer会把控制权转交给调度器以通知下一个协程的运行,调度器就会唤醒下一个协程)

image-20230820004240299

a协程想切换到b协程,a内部调用transfer,调用yield返回唤醒a的dispatch的resume调用,resume调用返回接收到a协程调用yield传递过来的callback,然后调用callback唤醒b协程。

local coroutines = {}

function transfer(name)
    local callback = function()
        return coroutine.resume(coroutines[name])
    end
    coroutine.yield(callback)
end

-- 注册三个线程

coroutines["print a"] = coroutine.create(function()
    while true do
        print("a")
        transfer("print b")
    end
end)
coroutines["print b"] = coroutine.create(function()
    while true do
        print("b")
        transfer("print c")
    end
end)
coroutines["print c"] = coroutine.create(function()
    while true do
        print("c")
        transfer("print a")
    end
end)

-- 调度器
dispatch = coroutine.create(function()
    local callback = nil
    while true do
        if callback == nil then
            _, callback = coroutine.resume(coroutines["print a"]) -- 起始线程 
        end
        _, callback = callback()
    end
end)

coroutine.resume(main)

25.1

改进getvarvalue,使之能处理不同的协程

function co_getvarvalue(co, name, level, isenv)
    if type(co) ~= "thread" then
        co = coroutine.running()
    end
    local value
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(co, level, i)
        if not n then
            break
        end
        if n == name then
            value = v
            found = true
        end
    end
    if found then
        return "local", value
    end

    -- 寻找非局部变量
    local func = debug.getinfo(co, level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == name then
            return "upvalue", v
        end
    end

    if isenv then
        return "noenv"
    end

    -- 寻找环境变量
    local _, env = co_getvarvalue(co, "_ENV", level, true)
    if env[name] then
        return "global", env[name]
    else
        return "noenv"
    end
end

local val1 = 1
local co = coroutine.wrap(function()
    local val2 = val1
    print(co_getvarvalue(nil, "val1", 1))
    print(co_getvarvalue(nil, "val2", 1))
end)
co()
print(co_getvarvalue(nil, "val1", 1))
print(co_getvarvalue(nil, "val2", 1))

_ENV

print(_G._G)
do
    _ENV = {
        print = _G.print -- _G是外层_G的_G
    }
    a = 1
    print(a)
    do
        b = 2
        print(b)
        do
            _ENV = {
                print = print --  如果_G.print的_G是外层_ENV的_G,所以结果是nil
            }
            c = 3
            print(c)
            do
                d = 4
                print(4)
            end
        end
    end
end

25.2 ⭐

请编写一个函数与getvarvalue类似的setvarvalue

function getvarvalue(name, level, isenv)
    local value
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(level, i)
        if not n then
            break
        end
        if n == name then
            value = v
            found = true
        end
    end
    if found then
        return "local", value
    end

    -- 寻找非局部变量
    local func = debug.getinfo(level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == name then
            return "upvalue", v
        end
    end

    if isenv then
        return "noenv"
    end

    -- 寻找环境变量
    local _, env = getvarvalue("_ENV", level, true)
    if env[name] ~= nil then
        return "global", env[name]
    else
        return "noenv"
    end
end

function setvarvalue(name, value, level, isenv)
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(level, i)
        if not n then
            break
        end
        if n == name then
            debug.setlocal(level, i, value)
            found = true
        end
    end
    if found then
        return "local change\t" .. name .. "=>" .. value
    end

    -- 寻找非局部变量
    local func = debug.getinfo(level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == name then
            debug.setupvalue(func, i, value)
            return "upvalue change\t" .. name .. "=>" .. value
        end
    end

    if isenv then
        return "noenv"
    end

    -- 寻找环境变量
    local _, env = getvarvalue("_ENV", level, true)
    if env[name] then
        env[name] = value
        return "global change\t" .. name .. "=>" .. value
    else
        return "noenv"
    end
end

a = "xx"
-- local a = 4;
print(getvarvalue("a"))
setvarvalue("a", 8)
print(getvarvalue("a"))

25.3

请编写函数getvarvalue的另一个版本,该函数返回一个包括调用函数可见的所有变量的表(返回的表中不应该包括环境中的变量,而应该从原来的环境中继承这些变量)

function getvarvalue(level, isenv)
    local res = {}
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(level, i)
        if not n then
            break
        end
        res[n] = v
    end
    -- 寻找非局部变量
    local func = debug.getinfo(level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == "_ENV" then -- 发现环境变量上值
            print("发现_ENV")
            mt = {}
            mt.__index = _ENV -- 继承
            setmetatable(res, mt)
            goto continue
        end
        res[n] = v
        ::continue::
    end
    return res
end

a = "1"
b = "2"
local c = 3
function test()
    local d = 4
    local e = c -- c是闭包用到的上值
    res = getvarvalue()
    for k, v in pairs(res) do
        print(k, v)
    end
    print("从继承的_ENV中寻找b", res["b"])
end
test()

25.4

请编写一个函数debug.debug的改进版,该函数再调用debug.debug的函数的词法定界中运行指定的命令(提示:在一个空环境中运行命令,并使用__index元方法让函数getvarvalue进行所有的变量访问)

a = {1, 2, 3}
debug.debug() -- 原版debug访问并修改了debug函数外的变量
print(#a)

--[[
> dofile 'test9.lua' 
lua_debug> a = {1,2}
lua_debug> cont      
2
]]

把 load 每次编译的代码理解为一次 do end 那么 local 也就只在当前代码段有作用,需要保存的变量要以非局部变量的方式保存到环境中。

function getvarvalue(name, level, isenv)
    local value
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(level, i)
        if not n then
            break
        end
        if n == name then
            value = v
            found = true
        end
    end
    if found then
        return value
    end

    -- 寻找非局部变量
    local func = debug.getinfo(level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == name then
            return v
        end
    end

    if isenv then
        return "noenv"
    end

    -- 寻找环境变量
    local env = getvarvalue("_ENV", level, true)
    if env[name] ~= nil then
        return env[name]
    else
        return "noenv"
    end
end

function mydebug()
    myENV = {
        print = print
    }
    mt = {}
    mt.__index = function(table, name)
        return getvarvalue(name, 1) -- 会截取第一个参数
    end
    setmetatable(myENV, mt)
    while true do
        io.write("debug > ")
        line = io.read()
        if line == "cont" then
            break
        end
        assert(load(line, nil, "bt", myENV))()
    end
end

hello = "1234"
mydebug()

--[[
> dofile '25.4.lua'   
debug > print(hello) 
1234
]]

想保留值的类型提示,可以改成返回表。

function getvarvalue(name, level, isenv)
    local value
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(level, i)
        if not n then
            break
        end
        if n == name then
            value = v
            found = true
        end
    end
    if found then
        return {"local", value}
    end

    -- 寻找非局部变量
    local func = debug.getinfo(level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == name then
            return {"upvalue", v}
        end
    end

    if isenv then
        return {"noenv", nil}
    end

    -- 寻找环境变量
    local env = getvarvalue("_ENV", level, true)[2]
    if env[name] ~= nil then
        return {"global", env[name]}
    else
        return {"noenv", nil}
    end
end

function mydebug()
    myENV = {
        print = print
    }
    mt = {}
    mt.__index = function(table, name)
        return getvarvalue(name, 2)[2]
    end
    setmetatable(myENV, mt)
    print(myENV.hello)
end

hello = "1234"
mydebug()

25.5 ⭐

改进上例,使之也能处理更新操作

function getvarvalue(name, level, isenv)
    local value
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(level, i)
        if not n then
            break
        end
        if n == name then
            value = v
            found = true
        end
    end
    if found then
        return value
    end

    -- 寻找非局部变量
    local func = debug.getinfo(level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == name then
            return v
        end
    end

    if isenv then
        return "noenv"
    end

    -- 寻找环境变量
    local env = getvarvalue("_ENV", level, true)
    if env[name] ~= nil then
        return env[name]
    else
        return "noenv"
    end
end

function setvarvalue(name, value, level, isenv)
    local found = false

    level = (level or 1) + 1

    -- 寻找局部变量
    for i = 1, math.huge do
        local n, v = debug.getlocal(level, i)
        if not n then
            break
        end
        if n == name then
            debug.setlocal(level, i, value)
            found = true
        end
    end
    if found then
        return "local change\t" .. name .. "=>" .. value
    end

    -- 寻找非局部变量
    local func = debug.getinfo(level, "f").func
    for i = 1, math.huge do
        local n, v = debug.getupvalue(func, i)
        if not n then
            break
        end
        if n == name then
            debug.setupvalue(func, i, value)
            return "upvalue change\t" .. name .. "=>" .. value
        end
    end

    if isenv then
        return "noenv"
    end

    -- 寻找环境变量
    local env = getvarvalue("_ENV", level, true)
    if env[name] then
        env[name] = value
        return "global change\t" .. name .. "=>" .. value
    else
        return "noenv"
    end
end

function mydebug()
    myENV = {
        print = print
    }
    mt = {}
    mt.__index = function(table, name)
        return getvarvalue(name, 2) -- 会截取第一个参数
    end
    mt.__newindex = function(table, name, value)
        setvarvalue(name, value, 2)
    end
    setmetatable(myENV, mt)
    while true do
        io.write("debug > ")
        line = io.read()
        if line == "cont" then
            break
        end
        assert(load(line, nil, "bt", myENV))()
    end
end

hello = "1234"
mydebug()

--[[
> dofile '25.5.lua'
debug > print(hello)      
1234
debug > hello = "2345"      
debug > print(hello)   
2345
]]

25.6

实现25.3节中开发的基本性能调优工具中的一些建议的改进

local Counters = {}
local Names = {}

local function hook()
    local f = debug.getinfo(2, "f").func
    local count = Counters[f]
    if count == nil then
        Counters[f] = 1
        Names[f] = debug.getinfo(2, "Sn")
    else
        Counters[f] = count + 1
    end
end

-- 排序
a = function()
    print(1)
end
b = function()
    print(1)
end
c = function()
    print(1)
end
Counters[a] = 300
Counters[b] = 100
Counters[c] = 200
Names[a] = "print a"
Names[b] = "print b"
Names[c] = "print c"
s = {}
for f, name in pairs(Names) do
    s[#s + 1] = f
end
table.sort(s, function(a, b)
    return Counters[a] > Counters[b]
end)
for _, f in ipairs(s) do
    print(Names[f])
end

25.8

示例25.6中沙盒的问题之一在于沙盒中的代码不能调用其自身的函数。请问如何纠正这个问题。

思路很简单,沙盒提供一个函数用于注册自己创建的函数,运行自己创建的函数也需要在沙盒环境的限制下运行

标签:练习题,25,end,22,--,print,return,function,local
From: https://www.cnblogs.com/linxiaoxu/p/17644283.html

相关文章

  • 西农2022级ACM招新考题
    准备放弃一段时间算法。西农2022级ACM招新上周结束了,五一假期研究了一下题解,整理发在博客。1.这真的是签到题print("\"ACMwelcomesyou\\n\"")2.4和数#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e6+10;intf[maxn+1];intl,r;boolche......
  • 「C」2022/10/26晚学习总结
    2022/10/26晚学习总结主要内容范围:教材23章今晚浅学了一点点东西,记录一下.fma函数在math.h里,浮点数乘加,比自己手动算精度高.doublefma(doublex,doubley,doublez);返回值:x*y+zmemcpy函数在string.h里,内存复制,他和strcpy的区别是,他不仅仅能复制字符......
  • Adobe Photoshop官方软件Photoshop 2022正式版下载 系列软件
    Photoshop2022v23.0.2.101是由Adobe公司最新推出的高效、专业、实用的图像处理软件,同时该软件主要是以其强悍的编辑和调整、绘图等功能得到广泛的应用,其中还有各种图片的调整和图画绘制以及图像的修复、调色等一系列的工具都是数不胜数,使用范围也是非常的广,我们从照片修饰到海报......
  • P1 P2508 [HAOI2008]圆上的整点
    [HAOI2008]圆上的整点23.3.22WE.真是一道神题,特别是对于刚得了甲流滚回家摆烂从而有时间乱看而恰巧这几天上课刚学复数的我。一直很好奇复数到底是什么,昨天晚上刷B站学习偶然看到了一个解释虚数的视频,结果也没看懂,只听说乘上一个\(i\)相当于旋转\(90^{\circ}\),一想还真是!......
  • CMPSC122 Matrix类实现细节
    CMPSC122MatrixMatrixClassAmatrixisrectangulararrayofitemslaidoutinrowsandcolumns.Thedimensions,orsize,ofamatrixcanbeexpressedasmxnorm-by-n,wheremisthenumberofrowsinthematrixandnisthenumberofcolumnsinthemat......
  • 朝花夕拾:NHOI 2022 T6
    原题题意:题目描述给定一颗树有\(n\)个结点,每个结点上有一个权值\(a_i\),对于每条至少包含两个点的简单路径,它的贡献为路径上点的数量(包括端点)\(\times\)路径上所有点的\(a_i\)的最大公约数(gcd)。求所有简单路径的贡献之和,对\(998244353\)取模。......
  • 在 Ubuntu 22.04 系统上为 SSH 开启基于时间的 TOTP 认证
    前言一次性密码(英语:one-timepassword,简称OTP),又称动态密码或单次有效密码,是指电脑系统或其他数字设备上只能使用一次的密码,有效期为只有一次登录会话或一段短时间内。基于时间的一次性密码算法(英语:Time-basedOne-TimePassword,简称:TOTP)是一种根据预共享的密钥与当前时间计算一次......
  • CSP模拟25
    炒币、凑数、同构、最近公共祖先A.炒币举个栗子,对于序列\[1,4,5\]在\(1\)处买进,在\(5\)处卖出是最优的选择。为什么不选择在\(4\)处买,因为\(4\)处成本更高,所以我们可以把一段递增或递减的序列缩成几个互不相同的点。例如\[1,3,5,3,2,7\]变成\[5,2,7\]只有这......
  • 2022 上海闵行高三一模英语订正
    I卷除听力订正语法填空第25题,根据文章第一句话可以知道:英国最近才推出政策。用过去式不好,而【现在进行时/一般现在时/现在完成时】都是可以的,填istaking/takes/hastaken。第30题,句意很清楚:“无论政策和规定有什么不同,有一件事很清楚……”,但是不知道两个空的【无论......
  • 【22.0】课程页面搭建
    【一】原型图【二】前端页面搭建【1】免费课页面<template><divclass="course"><Header></Header><divclass="main"><!--筛选条件--><divclass="condition"><ulclass="c......