素数环
总时间限制: 1000ms 内存限制: 65536kB
描述
输入正整数n,把整数1,2,3,…,n组成一个环,使得相邻两个整数之和均为素数。小强同学看过这个题,笑了:呵呵,打表!
Mr. Wu为了阻止小强打表,决定这样:
把全部的解按字典序排序后,从1开始编号,依次输出指定编号的k组解。最后一行输出总的方案数。同一个素数环只算一次。
输入
第1行:2个整数,n(n<=18)和k(1<=k<=10)
第2行:共有k个从小到大排列的整数,表示要输出的解的编号。
输出
前k行,每行一组解,对应于一个输入
第k+1行:一个整数,表示总的方案数。
样例输入
10 4
1 2 5 8
样例输出
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 10 9 8 5 6
1 2 3 8 5 6 7 10 9 4
1 2 3 10 9 8 5 6 7 4
96
提示
输入样例说明:
对1,2,…,10组成素数环。要输出字典序的第1,2,5,8等4组解
输出样例说明:
第1,2,5,8组解分别是样例中所列的4行。总共有96组解。
思路点拔:典型深搜,先写一个判断质数的函数,搜索是,判断没相邻两个数的和是否为素数,由于本题是一个环,所以再判断一下
#include
#include
int b[23],ans,m,n,tot,c[23],a[23]={0,1},t=1;
bool zs(int x,int y) //判断质数
{
int ans=x+y;
for(int i=2;i<=sqrt(ans);i++)
{
if(ans%i==0)
return 0;
}
return 1;
}
void print() //输出函数
{
for(int i=1;iprintf("%d ",a[i]);
printf("%d\n",a[m]);
}
void dfs(int k) //搜索
{
for(int i=2;i<=m;i++)
{
if(zs(a[k-1],i)==1&&b[i]==0) //判断相邻两个数的和是否为质数,并且没有用过
{
b[i]=1;
a[k]=i;
if(k==m&&zs(a[k],a[1])==1)
//如果填满了,再判断一下最后一个数与第一个数的和是否为素数
{
tot++;//如果是,总方案数加1
if(tot==c[t]) //如果是我们想要的那组数据
{
t++;
print(); //输出
}
}
else dfs(k+1); //继续搜索填充下一个数
b[i]=0;//回溯
}
}
}
int main()
{
scanf("%d %d",&m,&n);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
dfs(2);//搜索
printf("%d\n",tot);输出总方案数
return 0;
}
细心的读者会发现,上面的代码看上去万无一失,但会超时,因为在dfs中反
复的调用zs函数,时间复杂度会很高,所以关于质数,需要用另外一种方
式处理——由于本题中n小于等于18,所以所有数都不可能大于35,所以
用一个数组,若这个元素的下标为素数,如a[2],a[3],a[7]等就赋为1,否则
就赋为0,注意:本题必须用格式输入输出,因为这个方法是本题唯一的
正解,它的运行时间本来就临近超时,(700<=t<1000),如果用流输入
输出,同样会超时,废话不多说,上代码!
#include
#include
int b[23],ans,m,n,tot,c[23],a[23]={0,1},t=1;
int zs[35]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0};
void print() //输出函数
{
for(int i=1;iprintf("%d ",a[i]);
printf("%d\n",a[m]);
}
void dfs(int k) //搜索
{
for(int i=2;i<=m;i++)
{
if(zs[a[k-1]+i]==1&&b[i]==0) //判断相邻两个数的和是否为质数,并且没有用过
{
b[i]=1;
a[k]=i;
if(k==m&&zs[a[k]+a[1]]==1)
//如果填满了,再判断一下最后一个数与第一个数的和是否为素数
{
tot++;//如果是,总方案数加1
if(tot==c[t]) //如果是我们想要的那组数据
{
t++;
print(); //输出
}
}
else dfs(k+1); //继续搜索填充下一个数
b[i]=0;//回溯
}
}
}
int main()
{
scanf("%d %d",&m,&n);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
dfs(2);//搜索
printf("%d\n",tot);输出总方案数
return 0;
}
思路很简单,但有很多坑,需要多加注意哦~