POJ_3842_An Industrial Spy_筛法、素数表

三观又被毁了。。


题意:

给出最少一个数字,最多七个数字,问由这些数字最多能组成多少个素数。



Input

The first line of the input holds the number of test cases c (1 <= c <= 200). Each test case consists of a single line. This line contains the digits (at least one, at most seven) that are on the paper snippets.

Output

For each test case, print one line containing the number of different primes that can be reconstructed by shuffling the digits. You may ignore digits while reconstructing the primes (e.g., if you get the digits 7 and 1, you can reconstruct three primes 7, 17, and 71). Reconstructed numbers that (regarded as strings) differ just by leading zeros, are considered identical (see the fourth case of the sample input).


真心给这题数据跪了,最容易想到的的做法自然是先筛出10^7里的所有素数,然后dfs构造产生的数字,查表是否是素数然后给答案加一下就行了。算一下复杂度,筛法nlogn,dfsl!,素数判断O(1),数据组数200,在10^7级别。

然后就TLE了。

NMB啊NMB!!!

最后是减少筛法开销,筛出sqrt(n)的素数,然后跑表判断,然后就A了

我TM不服啊,我就算复杂度和操作数啊,然后后面那个办法的最差情况比筛法要差多了,但是那种情况直观上感觉很难出现,考虑平均数据确实可能更优。

但是我TM还是不服啊!!!因为我加操作数记录跑了下TLE的程序,发现才5*10^7啊我靠,这么小超时你妹啊!!!操作用时的常数是有多大啊你妹!!!


最后还是贴上AC代码,以后即使碰到很奇怪的超时,也要想一想分块的方法,就跟上次哈希那个题一样。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define mxl 10
#define mxn 10000010
#define sqrtmxn 3400
int len;
char a[mxl];
bool is_prime[sqrtmxn];
int prime[sqrtmxn],cnt;
bool shown[mxn];
bool flag[mxl];
int ans;
void set_prime(){
	cnt=0;
	memset(is_prime,true,sizeof(is_prime));
	is_prime[0]=is_prime[1]=false;
	for(int i=2;i<sqrtmxn;++i)	if(is_prime[i]){
		prime[cnt++]=i;
		for(int j=i*2;j<sqrtmxn;j+=i)
			is_prime[j]=false;
	}
}
bool judge(int in){
	if(in==0||in==1)	return false;
	for(int i=0;i<cnt;++i)	if(in%prime[i]==0){
		if(prime[i]>=in)	break;
		return false;
	}
	return true;
}
void init(){
	ans=0;
	memset(shown,false,sizeof(shown));
	memset(flag,false,sizeof(flag));
}
void dfs(int now){
	for(int i=0;i<len;++i){
		if(a[i]=='0'&&!now)	continue;
		if(!flag[i]){
			int tem=now*10+(a[i]-'0');
			if(!shown[tem]){
				shown[tem]=true;
				flag[i]=true;
				if(judge(tem))	++ans;
				dfs(tem);
				flag[i]=false;
			}
		}
	}
}
int main(){
	set_prime();
	int cs;
	scanf("%d",&cs);
	while(cs--){
		init();
		scanf("%s",a);
		len=strlen(a);
		dfs(0);
		printf("%d\n",ans);
	}
	return 0;
}



然后刚才去问铲神师兄为什么会T,才想起来我用的筛法是O(nlogn)的。。。。

埃氏筛法第二重循环不用从2*i开始,从i*i开始就行了,理由也很朴素。。。前队友之前还跟我提过我的筛法模板有问题。。。。。。

挑战这个混蛋,代码写错了。。。。

换了筛法以后就用正常的姿势A了。

为什么网上的题解都是说查素数表的!!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define mxl 10
#define mxn 10000010
int len;
char a[mxl];
bool prime[mxn];
bool shown[mxn];
bool flag[mxl];
int ans;
void set_prime(){
	memset(prime,true,sizeof(prime));
	prime[0]=prime[1]=false;
	for(long long i=2;i<mxn;++i)	if(prime[i])
		for(long long j=i*i;j<mxn;j+=i)
			prime[j]=false;
}
void init(){
	ans=0;
	memset(shown,false,sizeof(shown));
	memset(flag,false,sizeof(flag));
}
void dfs(int now){
	for(int i=0;i<len;++i){
		if(a[i]=='0'&&!now)	continue;
		if(!flag[i]){
			int tem=now*10+(a[i]-'0');
			if(!shown[tem]){
				shown[tem]=true;
				flag[i]=true;
				if(prime[tem])	++ans;
				dfs(tem);
				flag[i]=false;
			}
		}
	}
}
int main(){
	set_prime();
	int cs;
	scanf("%d",&cs);
	while(cs--){
		init();
		scanf("%s",a);
		len=strlen(a);
		dfs(0);
		printf("%d\n",ans);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值