2022.10.12 闲话
i want to make a public contest
看了一下 cppreference 的 dependent name,ODR 规则 和 ADL,深感 C++ 之牛逼啊 .
选两个比较高级的绝世好题:
- 给定一棵有根树,动态加点,支持换根,实时查询重链剖分的链数(多个重儿子取编号最小) — fhqtreap
- 给你一个二分图,请求出它的七元环数量 — dottle(这个好像骗过 joke3579).
如何出一道诈骗题呢?
Calc
给一个正整数 \(n\),求
\[\sum_{j=2}^n\left\lfloor\dfrac{(j-1)!+1}{j}-\left\lfloor\dfrac{(j-1)!}{j}\right\rfloor\right\rfloor \]\(1\le n\le 10^{12}\) .
Koishi Loves Construction
给一个 \(n\),要求:
- Task 1:试判断能否构造并构造一个长度为 \(n\) 的 \(1 \dots n\) 的排列,满足其 \(n\) 个前缀和在模 \(n\) 的意义下互不相同 .
- Task 2:试判断能否构造并构造一个长度为 \(n\) 的 \(1 \dots n\) 的排列,满足其 \(n\) 个前缀积在模 \(n\) 的意义下互不相同 .
如果能构造,构造一组方案 .
\(1\le n\le 10^5\) .
lambda 表达式实现递归的几种方案 (C++)
为什么 Python 的 lambda 表达式能直接使用递归啊?
以下 [&]
,[=]
和 []
不做区分(随便用 hhh).
以下的实例用一个简单递归函数演示
int f(int x){return x < 1 ? 0 : f(x-1) + 1;}
1. 使用 std :: function 包装
就是用 std :: function
包装后它就不是匿名的了,后面该咋写咋写就完了 .
类似于 C# 的
Func<int, int> f = null;
f = x => x < 1 ? 0 : f(x-1) + 1;
第一句就是先把它放着(声明)然后再用,当然这个做法在 C# 是有一定缺陷的(因为 C# 特性),但是在 C++ 里没有 .
一份实现:
auto f = [](int n)
{
std :: function<int(int)> _;
_ = [&](int n){return n < 1 ? 0 : 1 + _(n-1);};
return _(n);
};
好像后面的做法都要 since C++14 .
2. 将自身作为参数传入
这个是最常用且最简单的了 .
不多说,直接放代码:
auto f = [](auto&& self, int x){return x < 1 ? 0 : self(self, x-1) + 1;};
传的时候要传一下 self
,别的就没有什么太大的缺点了 .
3. 使用 Generic Lambda 代替方法 2 中传参
这个是最方便的了 .
std :: function<int(int)> f = [&f](int n){return n < 1 ? 0 : f(n-1) + 1;};
这里不能用 auto
,因为这里的类型相当于递归了,auto
的话编译器推不出来类型 .
其实 Generic Lambda 就相当于带 template 的 lambda 表达式 .
4. 使用 Y Combinator
具体需要一些 \(\lambda\) 演算的知识,可以去 Wikipedia 看一下 Lambda Calculus,\(\alpha\text{-}\rm equivalent\),\(\beta\text{-}\rm{reduction}\),\(\eta\text{-}\rm{conversion}\) 等 .
我们知道 Y 组合子(Y Combinator)是不动点组合子的一种,因为 Y 组合子相比其他不动点组合子非常容易实现所以采用 Y 组合子 .
Y 组合子:λf.(λx.f(x x))(λx.f(x x))
.
翻译成 C++(下面是一个 std :: function<int(int)>
版本的):
auto y = [](auto f)
{
return [&](auto _){return _(_);}([&](const auto& rec) -> std :: function<int(int)>
{
return f([&](int arg){return rec(rec)(arg);});
});
};
使用只需要传入一个原函数的高阶函数即可:
auto inr = [](auto f){return [&](int n){return n < 1 ? 0 : f(n-1) + 1;};};
printf("%d\n", y(inr)(114514)); // 别爆栈了 /hsh
以下是博客签名,正文无关
本文来自博客园,作者:Jijidawang,转载请注明原文链接:https://www.cnblogs.com/CDOI-24374/p/16785659.html
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0)进行许可。看完如果觉得有用请点个赞吧 QwQ