poj3292 Semi-prime H-numbers

这个题目感觉有点恶心,题目看了40多分钟猜看懂是啥意思,写了一遍又TLE。后来仔细想想,好像是可以预处理:将所有的结果全部存起来,然后再按照每1000个数一段统计各段的符合条件的个数。最后求一下和,再将不能整除的部分逐一判断就行。时间复杂度就会降低很多。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<set>
#define MAX 1000010
#define ll __int64

using namespace std;

ll p[MAX],a[MAX],q[MAX];
bool mark[MAX],sign[MAX],res[MAX];

int main(){
	memset(mark,false,sizeof(mark));
	memset(sign,false,sizeof(sign));
	memset(res,false,sizeof(res));
	int c = 0;
	for (c = 0; c*4+1<MAX; c++){
		p[c] = c*4+1;
		mark[p[c]] = true;	
	}
		
	int u = 0;
	for (int i = 1; i<c; i++)
		for (int j = i; p[i]*p[j] < MAX; j++) if (mark[p[i]*p[j]]) sign[p[i]*p[j]] = true;
	
	for (int i = 1; i<c; i++) if (mark[p[i]] && !sign[p[i]]) a[u++] = p[i];
	
	//for (int i = 0; i<100; i++) printf("%lld ",a[i]); printf("\n");
	
	for (int i = 0; i<u; i++){
		for (int j = i; a[i]*a[j] < MAX; j++) if (mark[a[i]*a[j]] && !res[a[i]*a[j]]){   //
			res[a[i]*a[j]] = true;
		}
	}
	
	int v = 0;
	memset(q,0,sizeof(q));
	for (int i = 1; i<MAX; i++){
		if (i % 1000 == 0){
			v++;
		} 
		if (res[i]){
			q[v]++;
		}
	}
	
	int n;
	while (scanf("%d",&n) && n != 0){
		int ans = 0;
		for (int i = 0; i<n/1000; i++) ans += q[i];
		for (int i = n/1000*1000; i<=n; i++) if (res[i]) ans++;
		printf("%d %d\n",n,ans);
	}
	return 0;
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值