kk的签到题(数据加强版) ---题解

 题意如上,数据加强版对n的最大值进行了加大,从原来的1000加到了1000000,如果还是用暴力求解的方法的话,那么一共最高500次查询,每次都暴力求解的话,时间复杂度达到了500 * 1e6,也就是5e8,对于计算机计算而言,一般来说计算量达到1e8就大概率会超时(1s时限下)。所以此题我们无法再使用暴力求解。

我们可以想一想,对于每个n是有固定的值的,也就是说,第一个喜欢的数永远是1,第二个永远是2,第三个永远是4,第1000个永远是1666,也就是说,无论如何,值不会改变。按照我们之前暴力求解的思路,我们每次查询都要从1开始重新找,那么每次都有可能要查询100w次,那么显然不合理,这个时候就涉及到了预处理方法,也就是我们使用一个100w的数组,预先记录完100w个数,存下每个喜欢的数的值,在每次查询的时候,直接输出这个下标在数组中的值。这就叫预处理,通俗来讲就是提前处理,用的时候直接查询。这样的话我们只需要一次for循环从1到1000000。时间复杂度为1e6 + 500!

代码如下

#include<bits/stdc++.h> //万能头文件
typedef long long ll;
using namespace std;
int a[1010000];
void pre() { //预处理
	int s = 1; //s为当前的数
	for (int i = 1; i <= 1000000; i++) { //i表示的是第i个喜欢的数,最大到100w
		if (s % 3 != 0 && s % 10 != 3) { // 如果两个条件都不满足,那么说明该数为喜欢的数
			a[i] = s; //存下第i个喜欢的数为s
		}
		else {
			while (s % 3 == 0 || s % 10 == 3) {//否则一直循环,直到满足喜欢的数的条件为止
				s++;
			}
			a[i] = s;
		}
		s++;
	}
}
int main() {
	//ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int t;
	scanf("%d", &t);
	pre();
	while (t--) {
		int n;
		scanf("%d", &n);
		printf("%d\n", a[n]);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值