解析:用set来存独立幸福数,每次找到一个幸福数,用book来标记,不管其是否独立都放进set里面,然后在之后的遍历检验中,如果发现set里的幸福数依附于正在检验的数,就把其从set中删除。用vis来标记检验一个数时(记得每次都要初始化),它经过操作(每个数平方加和)所产生的所有数,如果发现有已经标记过的,则表示进入死循环,此时退出循环,继续遍历检验别的数即可。如果在遍历检验时,发现其已经被book标记,说明这个数是幸福数,但它依附于别的数,直接continue即可。
具体看代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define N 10001
using namespace std;
int change(int x)//把一个数转化为平方加和
{
int ret=0;
while(x)
{
ret+=pow(x%10,2);
x=x/10;
}
return ret;
}
bool prime(int n)//检验素数
{
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
return false;
}
}
return true;
}
int book[N];//标记幸福数
int vis[N];//标记每个数在执行操作时所产生的所有数
int u[N];//标记独立性
int main()
{
int a,b;
cin>>a>>b;
set<int>s;//存独立幸福数
for(int i=a;i<=b;i++)
{
int key=i;
if(book[key])
{
continue;
}
int flag=0;
memset(vis,0,sizeof(vis));
int h=0;
int x;
int w[N];
int cnt=0;
while(1)
{
w[cnt++]=key;
vis[key]=1;
h++;
x=change(key);
if(x==1)
{
break;
}
else if(book[x])//遇到之前可以迭代到1的数
{
break;
}
else if(vis[x])//进入死循环
{
flag=1;
break;
}
else
{
key=x;
}
}
if(!flag)
{
u[i]=u[x]+h;
s.insert(i);
for(int j=0;j<cnt;j++)
{
book[w[j]]=1;//标记幸福数
u[w[j]]=u[i]-j;//标记每个数的独立性,不管是否是独立幸福数
}
set<int>::iterator it;
it=s.find(x);
if(it!=s.end())//删除误存的非独立幸福数
{
s.erase(it);
}
}
}
if(s.size()==0)
{
cout<<"SAD"<<endl;
}
for(set<int>::iterator it=s.begin();it!=s.end();it++)
{
if(prime(*it))
{
cout<<*it<<" "<<2*u[*it]<<endl;
}
else
{
cout<<*it<<" "<<u[*it]<<endl;
}
}
return 0;
}