题目来源:http://noi.openjudge.cn/ch0407/7591/
7591:反质数
总时间限制: 1000ms 内存限制: 65536kB
描述
将正整数x 的约数个数表示为 g(x)。例如,g(1)=1,g(4)=3, g(6)=4。
如果对于任意正整数y,当 0 < y < x 时,x 都满足 g(x) > g(y), 则称 x 为反质数。整数 1,2,4,6 等都是反质数。
现在任意给定两个正整数M, N,其中,M <N <= 20000000,按从小到大输出其中(包括M 和 N)的所有反质数。如果没有,则输出大写的NO。
输入
一行,包含两个正整数M和N,用单个空格隔开。
输出
在一行内输出所有反质数,以逗号间隔。如果没有,则输出 NO。
样例输入
1 13
样例输出
1,2,4,6,12
-----------------------------------------------------
思路
暂时没有想到怎么用搜索做。用的打表的方法,首先在本地写一个打表程序计算出所有反质数,将这些反质数存在主程序的一个数组里,主程序直接用这个数组。
写打表程序的时候注意那个求n的约数个数的函数,枚举约数的时候枚举到sqrt(n)就行了,不用枚举到n,这样可以把打表程序的复杂度由O(n^2)降到O(n^1.5)
-----------------------------------------------------
代码
提交的主程序
// 主程序
#include<iostream>
using namespace std;
const int NMAX = 55;
int a[NMAX] = {1,
2,
4,
6,
12,
24,
36,
48,
60,
120,
180,
240,
360,
720,
840,
1260,
1680,
2520,
5040,
7560,
10080,
15120,
20160,
25200,
27720,
45360,
50400,
55440,
83160,
110880,
166320,
221760,
277200,
332640,
498960,
554400,
665280,
720720,
1081080,
1441440,
2162160,
2882880,
3603600,
4324320,
6486480,
7207200,
8648640,
10810800,
14414400,
17297280
};
int main()
{
int m,n,i;
bool flag = false;
cin >> m >> n;
for (i=0; i<=NMAX; i++)
{
if (a[i] >= m && a[i] <= n)
{
if (!flag)
{
flag = true;
cout << a[i];
}
else
{
cout << "," << a[i];
}
}
}
if (!flag)
{
cout << "NO";
}
return 0;
}
打表程序
// 打表程序
#include<iostream>
#include<fstream>
#include<vector>
#include<cmath>
using namespace std;
const int NMAX = 20000005;
int a[NMAX] = {}; // 约数个数
vector<int> fzs; // 反质数表
int yueshu(int n) // 求n的约数个数
{
int i = 1, ans = 2;
int lim = (int) sqrt(n);
if (n==1)
{
return 1;
}
for (i=2; i<=lim; i++)
{
if (n%i==0)
{
ans += 2;
}
}
if (lim*lim == n)
{
ans -= 1;
}
return ans;
}
int main()
{
int i,mymax=0;
ofstream fout ("0407_7591_table.txt");
for (i=1; i<NMAX; i++)
{
a[i] = yueshu(i);
}
for (i=1; i<NMAX; i++)
{
if (a[i]>mymax)
{
fzs.push_back(i);
mymax = a[i];
fout << i << endl;
}
}
fout.close();
return 0;
}