【NOI2022省选挑战赛 Contest3 B】集合(结论)(构造)

集合

题目链接:NOI2022省选挑战赛 Contest3 B

题目大意

你有一个多重集合,一开始有一个数,然后你可以做无限次两种操作之一:
选两个正整数 a,b,删掉它们并加入 a^b。
选一个正整数可以表示为 a^b 的形式(其中 a,b 不小于 2),删去它并加入 a,b。
然后问你 [1,n] 中有多少个数作为一开始集合中的数能使得可以通过变换得到任意数。

思路

一道非常神奇非常神仙的构造。

那这种从一个变到全部的我们不难想象到两种方法:
ii+1,或者你可以无限放大一个数,然后从 ii1

但是它这个是次方,不太好搞,考虑这个性质:abc=abc
那如果我们有两个数 a,bc,那我们可以这样:abc=abca,bca,b,c
那这个就是当你有一个数的时候,你可以利用另外一个数把它分解因数。
那自然它也是可逆的,即当集合中有三个数的时候,我们可以把任意两个数乘起来。

那这样次方就变成了乘法,看起来就可做多了。
然后我们会发现我们可以利用上面的性质无限放大一个数:
当我们有一个合数 ab(a3) 以及另外一个数的时候,我们就可以无限复制 b,然后无限个 b 合并在一起就是无限大。
怎么无限复制呢,看(题解)操作:aba,bbaaba1b,ab,然后 ab 再弄,就无限复制了。

然后如果有一个 b,k,那我们可以这样得到 k1b,kbk=bbk1b,b,k1
所以如果一个数是合法的,那它可以表示成 ab,其中 a,b 有一个是合数 ab(a3)

那这个条件太复杂,我们可以考虑变成 6 的合数。
然后你直接搞完就会发现它挂了。

有一个特别的东西就是 4
因为你搞搞会发现 24 是不行的,但是别的时候有个 4 是没问题的(a4=(a2)2)。
所以我们就不要求 6,然后最后减去多算的 16 即可。

代码

#include<cstdio> #define ll unsigned long long using namespace std; ll n, ans; ll prime[10000001]; ll np[10000001]; bool see[10000001]; void Init() { for (ll i = 2; i <= 10000000; i++) { if (!np[i]) prime[++prime[0]] = i, np[i] = i; for (ll j = 1; j <= prime[0] && i * prime[j] <= 10000000; j++) { np[i * prime[j]] = prime[j]; if (i % prime[j] == 0) break; } } } int main() { Init(); scanf("%llu", &n); for (ll i = 2; i * i <= n; i++) { if (see[i]) continue; for (ll j = 2, now = i * i; now <= n; now *= i, j++) { if (now <= n / now) see[now] = 1; if (np[i] != i || np[j] != j) ans += now; if (now > n / i) break; } } printf("%llu", ans - (ans >= 16) * 16); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/15946578.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2021-02-28 【ybt高效进阶3-4-4】恒星的亮度
点击右上角即可分享
微信分享提示