三观又被毁了。。
题意:
给出最少一个数字,最多七个数字,问由这些数字最多能组成多少个素数。
Input
Output
真心给这题数据跪了,最容易想到的的做法自然是先筛出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;
}