题意:给你一串数字,问你他们能组成多少个不同的素数。思路:枚举这些数字的组合的排列,打一张素数表直接判断。这题时间限制很紧啊(1000ms),在无限TLE之后,我把memset(vis,0,sizeof(vis))这句删除之后跑了844ms,险过,memset怎么会那么坑,不是说内部实现是调用批处理吗,为什么还那么慢???另外,打素数表的时候,注意姿势。。。,不然必然超时。
Ps:按照刚进实验室时某大三学长教我的那个写法打素数表时超时,当时他还说两种方法都一样,现在才发现坑了我们。下面是三个版本的:1.dfs+二进制枚举优化 (844ms)
1.dfs+二进制枚举优化 (844ms):
2. 普通dfs不加优化(969ms。。。):
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define MAXN 10000000
char isp[MAXN], visp[MAXN], vis[MAXN];
int a[10], t[10], sum;
void init(){
memset(isp, 0, sizeof(isp));
isp[0] = isp[1] = 1;
for(int i = 2;i*i<MAXN;i ++)
if(!isp[i])
for(int j = i*i;j < MAXN;j += i)
isp[j] = 1;
return;
}
int ToNum(int n){
int sum = 0;
for(int i = 0;i < n;i ++) sum = sum*10 + t[i];
return sum;
}
void dfs(int n, int dep){
if(dep == n){
int tmp = ToNum(n);
if(!isp[tmp] && !visp[tmp]){
sum++;
visp[tmp] = 1;
}
return;
}
for(int i = 0;i < n;i ++){
if(!vis[i]){
vis[i] = 1;
t[dep] = a[i];
dfs(n, dep+1);
vis[i] = 0;
}
}
}
int main(){
char str[10];
int tt, n, b[10];
init();
scanf("%d", &tt);
while(tt--){
memset(str, 0, sizeof(str));
scanf("%s", str);
int len = strlen(str);
for(int i = 0;i < len;i ++) b[i] = str[i]-'0';
memset(visp, 0, sizeof(visp));
int ans = 0;
int UP = (1 << len);
for(int i = 1;i < UP;i ++){
int k = 0;
for(int j = 0;j < len;j ++)
if(i & (1 << j)) a[k++] = b[j];
sum = 0;
//memset(vis,0,sizeof(vis); 这句加上就超时。。。
dfs(k, 0);
ans += sum;
}
printf("%d\n", ans);
}
return 0;
}
2. 普通dfs不加优化(969ms。。。):
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define MAXN 10000000
char isp[MAXN], visp[MAXN], vis[MAXN];
int a[10], t[10], sum;
void init(){
memset(isp, 0, sizeof(isp));
isp[0] = isp[1] = 1;
for(int i = 2;i*i<MAXN;i ++)
if(!isp[i])
for(int j = i*i;j < MAXN;j += i)
isp[j] = 1;
return;
}
int ToNum(int n){
int sum = 0;
for(int i = 0;i < n;i ++) sum = sum*10 + t[i];
return sum;
}
void dfs(int n, int dep, int cnt){
if(dep == cnt){
int tmp = ToNum(cnt);
if(!isp[tmp] && !visp[tmp]){
sum++;
visp[tmp] = 1;
}
}
for(int i = 0;i < n;i ++){
if(!vis[i]){
vis[i] = 1;
t[dep] = a[i];
dfs(n, dep+1, cnt);
vis[i] = 0;
}
}
}
int main(){
char str[10];
int tt, n;
init();
scanf("%d", &tt);
while(tt--){
memset(str, 0, sizeof(str));
scanf("%s", str);
int len = strlen(str);
for(int i = 0;i < len;i ++) a[i] = str[i]-'0';
memset(visp, 0, sizeof(visp));
int ans = 0;
for(int i = 1;i <= len;i ++){
//memset(vis, 0, sizeof(vis)); 加上就超时。。。
sum = 0;
dfs(len, 0, i);
ans += sum;
}
printf("%d\n", ans);
}
return 0;
}
3.C++ STL库 next_permutation(a,a+k)函数 + 二进制优化(813ms),可以看出并不比dfs快多少,况且没有调用ToNum函数,减少了程序运行时跳转的时间:#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define MAXN 10000000
using namespace std;
char isp[MAXN], visp[MAXN], vis[MAXN];
int a[10], t[10], sum;
void init(){
memset(isp, 0, sizeof(isp));
isp[0] = isp[1] = 1;
for(int i = 2;i*i<MAXN;i ++)
if(!isp[i])
for(int j = i*i;j < MAXN;j += i)
isp[j] = 1;
return;
}
int ToNum(int n){
int sum = 0;
for(int i = 0;i < n;i ++) sum = sum*10 + a[i];
return sum;
}
void dfs(int n, int dep){
if(dep == n){
int tmp = ToNum(n);
if(!isp[tmp] && !visp[tmp]){
sum++;
visp[tmp] = 1;
}
return;
}
for(int i = 0;i < n;i ++){
if(!vis[i]){
vis[i] = 1;
t[dep] = a[i];
dfs(n, dep+1);
vis[i] = 0;
}
}
}
int main(){
char str[10];
int tt;
init();
scanf("%d", &tt);
while(tt--){
memset(str, 0, sizeof(str));
scanf("%s", str);
int len = strlen(str);
sort(str, str+len);
memset(visp, 0, sizeof(visp));
int ans = 0, UP = (1 << len);
for(int i = 1;i < UP;i ++){
int k = 0;
for(int j = 0;j < len;j ++)
if((i >> j) & 1) a[k++] = str[j]-'0';
sum = 0;
//memset(vis,0,sizeof(vis)) 加上同样超时。。。
do{
int tmp = 0;
for(int i = 0;i < k;i ++) tmp = tmp*10+a[i];
if(!isp[tmp] && !visp[tmp]){
sum++;
visp[tmp] = 1;
}
}while(next_permutation(a, a+k));
ans += sum;
}
printf("%d\n", ans);
}
return 0;
}