首页 > 其他分享 >函数调用

函数调用

时间:2024-03-02 16:33:05浏览次数:24  
标签:函数 sum 函数调用 子函数 mul 我们

题目

https://www.luogu.com.cn/problem/P7077
这题给我好搞。不过思路精巧。

\(Solution\)

首先我们考虑一个比较简单的问题。
称函数1是加法,函数2是乘法,函数3是调用。

首先,要转换思路。原先暴力模拟,考虑函数顺序,\(O(Qn)\), 必炸。我们考虑统计每个函数对答案的贡献。这样是\(O(n)\)复杂度的。其次,我们在考虑贡献时,也不应该直接修改上去。如果对于一个函数2,这个做法瞬间就退化了。类比线段树的懒标记,我们想到,给他们打标记,最后一并计算就行了。记住一个性质:乘可以看成多次加

我们从简单问题入手:
在不考虑函数3的情况下,对于函数2,我们自然可以维护总乘积;对于函数1,我们可以维护一个\(mul[i]\),代表当前函数被乘的次数,注意这里,这个函数被乘的次数等于后面函数的\(mul\)之积。如果前后存在多个\(f[i]\), 那么计算也是一样的。这样我们最后把每个\(a[p]\)加上\(mul[i] * v\)就可以了。

接下来考虑函数3。做法搬过来。我们变一下\(mul\)定义:调用此函数时,全局乘了多少次。也就是后面的mul不用乘了。
先把\(mul\)维护好(下面要用,否则\(sum\)维护不出)。具体来说,我们对于每一个调用函数,按照拓扑逆序递推:

\[mul[u] = \prod \limits_{i \in son} mul[i] \]

我们发现,对于函数调用的函数(姑且称为子函数吧),他们的贡献没有被计算。我们这时候只维护\(mul\)是无法做的,因为子函数无法处理了,子函数会被父函数调用的次数影响。这启发我们维护\(sum[i]\),代表\(f[i]\)被调用的次数。具体来说,我们对于每个父函数(其实就是特判,他们永远只被调用一次)

\[sum[i] = \prod \limits_{j = i + 1}^Q mul[j] \]

对于每个子函数:

\[sum[u] = sum[father] * \prod \limits_{在u右边} mul[brother] \]

其实就是 父函数调用多少次 乘上后面兄弟乘了多少次
到现在为止应该能理解为什么不去\(mul\)了吧。因为后面兄弟调用的次数包括父节点调用次数,不能计算啦~,乘起来答案就不对了。

不要忘记要把相同的函数加起来~

那么我们最后就可以统计答案了~
对于函数1,维护总乘数,直接乘。对于函数2,由于可能做子函数,于是我们拿\(sum\)直接\(w[p] += v * sum[i]\)。

这样就把答案统计出来了。

原来维护的mul对现在不适用了。
因为原来的mul指的是对答案的贡献次数。而现在已经求出等效的\(sum[i]\),加上了,没必要了。mul目前的作用只有计算sum。
那么乘起来算就与sum[i]重复了。

总结:按拓扑逆序,先求单点挂着的\(mul\), 反向枚举sum[i], 算父函数后面乘积,在拓扑正序求出sum, 最后统计答案。

标签:函数,sum,函数调用,子函数,mul,我们
From: https://www.cnblogs.com/qinyiting/p/18048781

相关文章

  • GPT 中的函数调用(function call)是什么?
    在OpenAIChatGPTAPI和GoogleGeminiAPI中我们可以看到函数调用的功能。这个功能是做什么用的?下面大概讲解。以GoogleGeminiAPI函数调用一节中的内容为例,该章节举了一个例子:大语言模型(LLMs)往往无法进行准确的数学运算。比如说,给Gemini两个数\(a\)和\(b\),让它计......
  • C# 使用自定义特性标注类的方法,直接在当前类中让Main函数调用它
    有的时候我们想要再Main执行一些代码,如果直接在里面写的话,下次再想用的时候就会把之前的代码删掉,好不容易写的代码不想删掉于是我们可以将这些代码写到类文件中,想要执行了,就在Main中调用该类的方法,但是有的时候我们又懒的去Main函数指定的,有没有什么办法能直接在新类中就能指定......
  • GDB调试之函数调用栈管理(八)
    栈帧:当程序进行函数调用的时候,比如说在哪里调用,这些信息我们称之为栈帧。每一个栈帧的内容包括调用的参数,局部变量,寄存器等这些信息,这就是一个栈帧。调用栈:所有栈帧组成的信息称之为调用栈,或者我们也可以称之为调用堆栈。栈的特性是后进先出,函数调用也是这样,如果函数1里面调用了......
  • 基于TigerBot-13b训练其函数调用能力
    写在前面原生的tigerbot似乎并不支持函数调用,于是我来支持一下 数据集我在huggingface上找了个英文的数据集https://huggingface.co/datasets/sadmoseby/sample-function-call这里面包含了1k组的函数调用,这个数据集的特点如下:1.包含有单个/多个/没有函数调用的情形2.......
  • 多重继承下的虚函数调用
    C++中虚函数调用采用所谓的虚函数表(vtable)实现,对于简单的单继承,其实现如下图所示:(其中ClassA为ClassB的基类,详见深入浅出MFCP68)你也许会想到:C++支持多继承,在多继承的情况下,vatble以及内存布局该如何实现?以下也许就是你想要的答案代码:C继承于A和B,运行环境VC6.0classA......
  • f通过new关键词进行函数调用,之后无论如何都会返回一个与F关联的普通对象(因为不是通过
    varF=function(){};Object.prototype.a=function(){};Function.prototype.b=function(){};varf=newF();关于这段代码的描述,正确的是:Af能取到a,但取不到bBf能取到a,bCF能取到b,不能取到aDF能取到a,不能取到b正确答案:A网上有一道美团外卖的面试题是这样的:Function......
  • 【chatgpt问答记录】双端队列、栈和函数调用栈
    collections.deque和queue.Queue的区别Q:collections.deque()跟queue.Queue()有什么区别?collections.deque()和queue.Queue是两种不同的数据结构,它们有一些区别:实现方式:collections.deque()是Python标准库提供的双端队列数据结构,使用双向链表实现,具有高效的在两端进行......
  • C语言程序设计 求阶乘递归函数调用示例
    ......
  • JavaScript 函数、函数构造、函数调用、参数、函数返回值、变量的作用域、预解析
    一、函数及函数的构造函数是一个可重用的代码块,用来完成某个特定功能。每当需要反复执行一段代码时,可以利用函数来避免重复书写相同代码。函数包含着的代码只能在函数被调用时才会执行,就可以避免页面载入时执行该脚本简单来说就是一个封装,封装的是一个特定的功能,重复使用函......
  • Linux 函数调用的用户态与内核态
    在用户态中,程序的执行往往是一个函数调用另一个函数。函数调用都是通过栈来进行的。在进程的内存空间里面,栈是一个从高地址到低地址,往下增长的结构,也就是上面是栈底,下面是栈顶,入栈和出栈的操作都是从下面的栈顶开始的。32位操作系统在CPU里,ESP(ExtendedStackPointer)是栈顶指针......