P6583 回首过去 题解

不错的 Idea。当然如果熟练莫反就是另一回事,但我不熟练(

注意到如果最简分数 xy 是有限小数,那么 y 只能含有 2,5 这两个质因子(当然可以为 1)。

然而分数并不一定最简,所以考虑将分数变成 xgyg,xg,ygn 这个形式,其中保证 xy 最简,y 只含有 2,5 这两个质因子(或者为 1),x 任意,g 不能含有 2,5 这两个质因子。

显然合法的小于等于 ny 可以预处理,因此考虑枚举 y,g,注意到枚举 yy 限制过大不好化简,只能枚举出符合条件的 (y,g) 二元组的个数(人话:只能做到 O(n),可以自己手玩一下),因此考虑枚举 g,此时 y[1,ng],然后由于 y 只含有 2,5 这两个质因子,所以个数是很少的,又因为 g 递增时 y 递减,所以是单调的,能做到 O(n)(实际上枚举 y 也是利用这一点)。

注意到 n1012 因此猜想应该是个根号算法,考虑令 f(ng) 表示当前枚举 g 时合法的 y 的个数,那么最终答案如下:

1gn,2g,5gf(ng)ng

发现这是个整除分块的形式,但讨厌的是限制条件 2g,5g,考虑去掉这个限制条件,整除分块过程中处理出一段 ng 相同的区间 [l,r] 后,考虑计算这个区间内满足限制条件的 g 的个数 c,这个可以简单容斥,c=g(l,r,1)g(l,r,2)g(l,r,5)+g(l,r,10)g(l,r,x) 表示 [l,r]x 的倍数的个数,处理出 c 后整个区间的贡献就是 c×f(ng)ng

Code:

/*
========= Plozia =========
	Author:Plozia
	Problem:P6583 回首过去
	Date:2022/10/20
========= Plozia =========
*/

#include <bits/stdc++.h>
typedef long long LL;

const int MAXN = 1e6 + 5;
LL n, a[MAXN], cnta;

LL Read()
{
	LL sum = 0, fh = 1; char ch = getchar();
	for (; ch < '0' || ch > '9'; ch = getchar()) fh -= (ch == '-') << 1;
	for (; ch >= '0' && ch <= '9'; ch = getchar()) sum = (sum << 3) + (sum << 1) + (ch ^ 48);
	return sum * fh;
}
LL Min(LL fir, LL sec) { return (fir < sec) ? fir : sec; }
LL g(LL l, LL r, LL x) { return r / x - (l - 1) / x; }

int main()
{
	n = Read(); for (LL i = 1; i <= n; i <<= 1) for (LL j = i; j <= n; j *= 5) a[++cnta] = j;
	LL ans = 0; int p = cnta; std::sort(a + 1, a + cnta + 1);
	for (LL l = 1, r; l <= n; l = r + 1)
	{
		if (n / l == 0) r = n; else r = Min(n / (n / l), n);
		while (p > 0 && a[p] > n / l) --p;
		ans += (g(l, r, 1) - g(l, r, 2) - g(l, r, 5) + g(l, r, 10)) * (n / l) * p;
	}
	printf("%lld\n", ans); return 0;
}
posted @   Plozia  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示