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

集合

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

题目大意

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

思路

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

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

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

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

然后如果有一个 b , k b,k b,k,那我们可以这样得到 k − 1 k-1 k1 b , k → b k = b ∗ b k − 1 → b , b , k − 1 b,k\rightarrow b^k=b*b^{k-1}\rightarrow b,b,k-1 b,kbk=bbk1b,b,k1
所以如果一个数是合法的,那它可以表示成 a b a^b ab,其中 a , b a,b a,b 有一个是合数 a b ( a ⩾ 3 ) ab(a\geqslant 3) ab(a3)

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

有一个特别的东西就是 4 4 4
因为你搞搞会发现 2 4 2^4 24 是不行的,但是别的时候有个 4 4 4 是没问题的( a 4 = ( a 2 ) 2 a^4=(a^2)^2 a4=(a2)2)。
所以我们就不要求 ⩾ 6 \geqslant 6 6,然后最后减去多算的 16 16 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值