7-5合数(20分)备忘录和计数简化查找

合数是指在大于1的整数中除了能被1和本身整除外,还能被其他数(0除外)整除的数。
现在,请你求在一个合数的因子中,有几个因子是合数。例如,16的因子有1,2,4,8,16,其中4,8,16为合数,它有3个因子为合数。
现在,请你求范围1至n中,因子中合数个数为x的数的数量(多次询问)。
输入格式:
第一行输入两个整数 n,m(1≤n,m≤10
5
) 表示范围以及询问次数。
接下来 m 行,每行一个正整数 x(1≤x≤n),查询范围1至n中,因子中合数个数为x的数的数量
输出格式:
一个整数,即满足题意的答案。
输入样例:
在这里给出一组输入。例如:
10 5
1
2
3
4
5

思路

因为要计算1~n有多少个因子是合数,这里用i表示正在判断的数,因此我们必须要在找到一个数的因子之后,再进行判断是不是合数。显然除了1*i,所有的因子都是小于i的(在计算到i之前我们已经计算过这些数是否为合数),为了避免对这些数进行重复判断,因此用一个数组adjust来记录数字是否为合数,是的话记为1,不是则记为0。

判断一个数i是不是合数就是,除了1和本身外,还能被其他数整除,就每次从2开始尝试除这个数,在这里一旦可以除尽我们就将adjust[i]标记为1,我们用一个数组sum来存储一个数的合数因子的个数,为了省事,我们只进行到sqrt(i),因为已知J可以被i整除的话,i/j一定以可以被i整除,再通过adjust数组判断j和i/j是否为合数,是的话就sum[i]+1。当然sqrt[i]是一个例外,只用判断j就可以了。要注意一个特殊的点的是,如果这个数本身是一个合数的话,那么他本身也是一个合数因子。

现在我们已知1~n所有数字的因子中合数的个数,为了查询数量方便,避免多次重复遍历sum数组,再建立一个数组result,用result[i]来存储因子中合数个数为i的数量。最后根据输入的数据直接调取result[i]中的信息就可。

#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int main()
{
	int n, m;
	cin >> n >> m;
	vector<int> adjust(n + 1, 0);
	vector<int> sum(n + 1, 0);

	//显然1,2,3不是合数
	for (int i = 4; i < n+1; i++)
	{
		for (int j = 2; j <= sqrt(i); j++)
		{
			if (i % j == 0)
			{
				adjust[i] = 1;
				//当J不是sqrt(i)时,要判断j和i/j.
				if (j != sqrt(i))
				{
					if ( adjust[j] == 1)
					{
						sum[i]++;
					}

					if (adjust[i / j] == 1)
					{
						sum[i]++;
					}
				}//是sqrt(i)时只用判断j,因为此时i/j=j;
				else
				{
					if (adjust[j] == 1)
					{
						sum[i]++;
					}
				}
				
			}
			
		}
		if (adjust[i]==1)
		{
			sum[i]++;
		}
	}

	//计算因子中合数为i的数量
	vector<int> result(n + 1,0);
	for (int i = 0; i <= n; i++)
	{
		result[sum[i]]++;
	}
	
	/*for (int i = 0; i <=n; i++)
	{
		cout<<i<<':'<< adjust[i]<<"间隔"<<sum[i]<<"间隔"<<result[i]<<endl;
	}*/
	//打印结果
	int i;
	while (m--)
	{
		cin >> i;
		cout << result[i]<<endl;
	}
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下坠丷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值