[暴力题解系列+正经题解]好数

好数

虽然不是13号考的那批人,但是还是扔一个暴力题解在这里。

首先数据范围\(n\le 10^7\),就算纯粹暴力去做也只是\(O(nlogn)\),也就是直接从1到n去枚举。秉持着暴力就是要优化细节的精神,对题目进行一个分析,发现无论如何,个位数必须是奇数,否则必然不满足条件,那么优化手段就显而易见了:枚举只枚举奇数。直接把时间复杂度砍一刀成为\(O(\frac{n}{2}log\frac{n}{2})\)。实际优化性能如何呢?在我机子上跑,从\(1\)完全数到\(10^7\)需要0.08秒,而只枚举奇数就能变成0.05秒,要知道对于暴力来说,就算是0.03秒也是一种非常要命的资源。

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int n, cnt = 0;
	//n = 10000000;
	scanf("%d", &n);
	for(int i=1; i<=n; i+=2)
	{
		int temp = i;
		int eo = 1, is = 1; // 0为偶数,1为奇数 
		while(temp>0)
		{
			int c = temp % 10;
			temp /= 10;
			if(c%2 != eo)
				is = false;
			if(!is)
				break;
			eo = !eo;
		}
		if(is)
			cnt++;
	}
	printf("%d\n", cnt);
	return 0;
}

至于如果数据范围变大要怎么做呢?我在此之前思考过一个思路:由于每一个位置可用的数字其实是固定的,奇数位只能是13579(5个),偶数位只能是02468(5个),首位数字如果是偶数则只能用2468(4个)。因此可以基于排列组合的计算方式处理掉绝大部分数据。例如查询2024,就可以通过计算\(5+4\times5+5\times5\times5 = 150\)获得前面的数字(即1~999),随后可以通过相似的计算得到1000~2000的数据,然后继续分治得到2000~2020的数据,最终再直接枚举2020~2024的数据,即使面对\(1\le n\le 10^{100}\)也不可能爆时间。(拍胸脯)

但是下面的程序我就不想写了,因为已经写红温了。

posted @ 2024-04-14 12:40  ComputerEngine  阅读(14)  评论(0编辑  收藏  举报