1002. Anti-prime Sequences
| |
Description
Given a sequence of consecutive integers n,n+1,n+2,...,m, an anti-prime sequence is a rearrangement of these integers so that each adjacent pair of integers sums to a composite (non-prime) number. For example, if n = 1 and m = 10, one such anti-prime sequence is 1,3,5,4,2,6,9,7,8,10. This is also the lexicographically first such sequence. We can extend the definition by defining a degree danti-prime sequence as one where all consecutive subsequences of length 2,3,...,d sum to a composite number. The sequence above is a degree 2 anti-prime sequence, but not a degree 3, since the subsequence 5, 4, 2 sums to 11. The lexicographically .rst degree 3 anti-prime sequence for these numbers is 1,3,5,4,6,2,10,8,7,9.
Input
Input will consist of multiple input sets. Each set will consist of three integers, n, m, and d on a single line. The values of n, m and d will satisfy 1 <= n < m <= 1000, and 2 <= d <= 10. The line 0 0 0 will indicate end of input and should not be processed.
Output
For each input set, output a single line consisting of a comma-separated list of integers forming a degree danti-prime sequence (do not insert any spaces and do not split the output over multiple lines). In the case where more than one anti-prime sequence exists, print the lexicographically first one (i.e., output the one with the lowest first value; in case of a tie, the lowest second value, etc.). In the case where no anti-prime sequence exists, output No anti-prime sequence exists.
Sample Input
1 10 2 1 10 3 1 10 5 40 60 7 0 0 0
Sample Output
1,3,5,4,2,6,9,7,8,10 1,3,5,4,6,2,10,8,7,9 No anti-prime sequence exists. 40,41,43,42,44,46,45,47,48,50,55,53,52,60,56,49,51,59,58,57,54 |
代码:
#include<iostream>
#include<string.h>
using namespace std;
const int MAX=10001;// 由于d的上限是10,所以 MAX最大应该是1000(m的上界)的10倍左右,这里取10001
int m,n,d;
bool exist;
int vis[MAX];
int res[MAX];
int pri[MAX];
void init ()//频繁使用在1-10001阶段的素数判断,最好是先打好表存储起来,比较省时间
{
memset(pri,0,sizeof(pri));
pri[1] = 1; //若i是素数则pri[i]为1
for ( int i = 2; i <= 100; i++ )
{
if ( pri[i] ) continue;
for ( int j = 2; i * j < 10001; j++ )
pri[i*j] = 1;
}
}
bool judge(int step,int i)//判断是否符合规则
{
res[step]=i;
int sum=0;
int cnt=0;
for(int j=step; j>=0; j--)
{
sum+=res[j];
++cnt;
if(2<=cnt&&cnt<=d && !pri[sum])
{
return false;
}
}
return true;
}
void dfs(int step)
{
//若在其他已经搜索过的分支中 找到了满足要求的序列,则返回
if(exist) return ;
//若所有数字已经排完序,则返回,这句可以说是和下面的 if(exist) return; 是相对应的
if(step==m-n+1)
{
exist=true;
return ;
}
for(int i=n;i<=m;i++)
{
if(!vis[i]&&judge(step,i))
{
vis[i]=1;
dfs(step+1);
vis[i]=0;
}
if(exist) return;//没加上这句会WA
}
}
int main()
{
init();
while(cin>>n>>m>>d)
{
if(!n&&!m&&!d)break;
memset(vis,0,sizeof(vis));
// memset(res,0,sizeof(res));//由于res每次都会从0开始更新,所以可以偷懒不用清零
exist=false;
dfs(0);//搜索
if(exist)
{
cout<<res[0];
for(int i=1;i<=m-n;i++)
cout<<","<<res[i];
cout<<endl;
}
else cout<<"No anti-prime sequence exists."<<endl;
}
}