丑数描述
说法一:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但7、14不是,因为它们包含质因子7。 习惯上我们把1当做是第一个丑数。
前20个丑数为:1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36。
说法二:对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S。这个正整数集合包括,p1、p1*p2、p1*p1、p1*p2*p3...(还有其它)。该集合被称为S集合的“丑数集合”。注意:我们认为1不是一个丑数,丑数集合中每个数从小到大排列,每个丑数都是素数集合中的数的乘积。(如S={2,3,5}时,对应丑数集合为U={2,3,4,5,6,9,10,15,25,30})
回复https://ask.csdn.net/questions/871981
void 查找丑数(int 求数)
{/*说法一:把只包含质因子2,3和5的数称作丑数。例如6、8都是丑数,但7、14不是,因为它们包含质因子7。 习惯上我们把1当做是第一个丑数。*/
int 换 = 5;
bool 判 = false;
if (求数 % 2 == 0 || 求数 % 3 == 0 || 求数 % 5 == 0 || 求数 == 1)判 = true;
while (换 < 求数)
{
换 += 2;
if (换 % 3 == 0 || 换 % 5 == 0)continue;
if (求数%换 == 0)
{
//cout << 求数 << "非丑" << 换 << "; ";// && 求数 != 换
判 = false;
break;
}
}
if (判)cout << 求数 << "丑数" << "; ";
}
void 查找丑数(int 求数)
{/*说法一:把只包含质因子2,3和5的数称作丑数。例如6、8都是丑数,但7、14不是,因为它们包含质因子7。 习惯上我们把1当做是第一个丑数。*/
int 换 = 5;
bool 判 = false;
if (求数 % 2 == 0 || 求数 % 3 == 0 || 求数 % 5 == 0)判 = true;
while (判 && 换 < 求数)
{
换 += 2;
if (换 % 3 == 0 || 换 % 5 == 0)continue;
if (求数 % 换 == 0)
{
判 = false;//cout << 求数 << "非丑" << 换 << "; ";// 求数 != 换 &&
break;
}
}
if (判 || 求数 == 1)cout << 求数 << endl;//cout << 求数 << "丑数" << "; ";
}
int _tmain(int argc, _TCHAR* argv[])
{
起始:
clock_t start = clock();
int 数 = 1;
while(数<=1400)查找丑数(数++);
clock_t stop = clock();
printf_s("耗时:%lf\n", (double)(stop - start) / CLOCKS_PER_SEC);
//cout << endl;
//CTime time(CTime::GetCurrentTime());
//SYSTEMTIME timeDest;
//time.GetAsSystemTime(timeDest);
//int 年 = timeDest.wYear, 月 = timeDest.wMonth, 日 = timeDest.wDay;
//char 时间[128];
_strdate_s(时间, 128);
//_strtime_s(时间, 128);
printf("系统日期:%s\n", 时间);
//阳历节日日历(时间, 年, 月, 日);
system("pause");
goto 起始;
//return 0;
}
看过一些画蛇添足的直接求解程序,我这个直接求解程序使用的时间大为降低,效率大为提高。
bool 折半查找(int *数组, int 序, int 值)
{
int 头 = 0, 尾 = 序 - 1;
do
{
if (数组[尾] == 值)return true;
if (数组[头] == 值)return true;
} while (++头 <= --尾);
return false;
}
int 获取大于5的验证集合以提高验证速度(int 求数, int* 验证集合)
{
int 换 = 5;
int 验序 = 0;
while (换<求数 / 2)
{
换 += 2;
if (换 % 3 != 0 && 换 % 5 != 0)验证集合[验序++] = 换;
}
return 验序;
}
void 丑数优化(int *验组, int 验序, int 求数)
{
int 头 = 0, 尾 = 验序 - 1;
bool 判 = false;
if (求数 % 2 == 0 || 求数 % 3 == 0 || 求数 % 5 == 0)判 = true;
while (判 && 头 < 尾)
{
if (求数 % 验组[头++] == 0 || 求数 % 验组[尾--] == 0)
{
判 = false;
break;
}
}
if (判 || 求数 == 1)cout << 求数 << endl;
}
double 最小时间 = 100000;
int _tmain(int argc, _TCHAR* argv[])
{
起始:
int 数 = 1, 求数 = 100000, 序 = 0, 验证集合[100000 / 7] = { 0 };
序 = 获取大于5的验证集合以提高验证速度(求数, 验证集合);
clock_t start = clock();
while (数 <= 求数)丑数优化(验证集合, 序, 数++);
//while (数 <= 求数)查找丑数(数++);
clock_t stop = clock();
if ((double)(stop - start) / CLOCKS_PER_SEC < 最小时间)最小时间 = (double)(stop - start) / CLOCKS_PER_SEC;
printf_s("耗时:%lf\n", 最小时间);
//cout << endl;
//CTime time(CTime::GetCurrentTime());
//SYSTEMTIME timeDest;
//time.GetAsSystemTime(timeDest);
//int 年 = timeDest.wYear, 月 = timeDest.wMonth, 日 = timeDest.wDay;
//char 时间[128];
_strdate_s(时间, 128);
//_strtime_s(时间, 128);
printf("系统日期:%s\n", 时间);
//阳历节日日历(时间, 年, 月, 日);
system("pause");
goto 起始;
//return 0;
}
原算法与优化算法对比
最好的思路网络上有:方法二思路:后面的丑数肯定是已存在的丑数乘以2、3或者5,找到比现有丑数大的且是最小的丑数作为下一个丑数(如何找是关键)。用2分别从现有丑数中从前往后乘以丑数,找到第一个大于当前所有丑数的值以及位置,3、5同样如此,再把他们相乘之后的结果做对比,取最小的。下次将从上一次的位置开始往下找,这样将不会出现冗余。转录如下:
https://www.cnblogs.com/ys99/p/9307426.html
int Next_Ugly(int ugly_arr[], int *loc2, int *loc3, int *loc5, int *index) {
while (ugly_arr[*loc2] * 2 <= ugly_arr[*index]) (*loc2)++; //千万注意这里是小于等于,不要写成小于了
while (ugly_arr[*loc3] * 3 <= ugly_arr[*index]) (*loc3)++;
while (ugly_arr[*loc5] * 5 <= ugly_arr[*index]) (*loc5)++;
if (ugly_arr[*loc2] * 2< ugly_arr[*loc3] * 3) return (ugly_arr[*loc2] * 2 < ugly_arr[*loc5] * 5) ? ugly_arr[*loc2] * 2 : ugly_arr[*loc5] * 5;
else return (ugly_arr[*loc3] * 3) < ugly_arr[*loc5] * 5 ? ugly_arr[*loc3] * 3 : ugly_arr[*loc5] * 5;
}
int get_Ugly_sec(int num) {/*(2)方法二思路:后面的丑数肯定是已存在的丑数乘以2、3或者5,找到比现有丑数大的且是最小的丑数作为下一个丑数(如何找是关键)。用2分别从现有丑数中从前往后乘以丑数,找到第一个大于当前所有丑数的值以及位置,3、5同样如此,再把他们相乘之后的结果做对比,取最小的。下次将从上一次的位置开始往下找,这样将不会出现冗余。*/
int ugly_arr[1000];
int index = 0, value = 1;
int loc2 = 0, loc3 = 0, loc5 = 0;
while (value <= num) {
ugly_arr[index] = value;
cout << ugly_arr[index] << "\t";
//if ((index + 1) % 10 == 0) cout << endl;
value = Next_Ugly(ugly_arr, &loc2, &loc3, &loc5, &index);
index++;
}
return index;
}
double 最小时间 = 100000;
int _tmain(int argc, _TCHAR* argv[])
{
clock_t start = clock();
get_Ugly_sec(1000000);
clock_t stop = clock();
if ((double)(stop - start) / CLOCKS_PER_SEC < 最小时间)最小时间 = (double)(stop - start) / CLOCKS_PER_SEC;
printf_s("耗时:%lf\n", 最小时间);
}
更新程序:添加7即可实现H数;有么有2 3 5 7 9的,有的话,直接在我程序基础里面添加就是。
void 丑数(int 数)
{
int Lin = 数;
while (Lin>1)
{
if (!(Lin % 2) || !(Lin % 3) || !(Lin % 5))
{
if (!(Lin % 2))Lin /= 2;
if (!(Lin % 3))Lin /= 3;//使用else的话就不是并行处理
if (!(Lin % 5))Lin /= 5;
}
else return;
}
cout << 数 << ends;
}
int a = 1; while (++a <= 3000)丑数(a);