码迷,mamicode.com
首页 > 其他好文 > 详细

[CSP-S模拟测试]:Divisors(数学)

时间:2019-10-04 19:14:37      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:时间   san   区间   题意   $0   viso   数据   space   The   

题目描述

给定$m$个不同的正整数$a_1,a_2,...,a_m$,请对$0$到$m$每一个$k$计算,在区间$[1,n]$里有多少正整数是$a$中恰好$k$个数的约数。


输入格式

第一行包含两个正整数$n,m$,分别表示区间范围以及$a$数组的大小。
第二行包含$m$个不同的正整数$a_1,a_2,...,a_m$,表示$a$数组。


输出格式

输出$m+1$行,每行一个整数,其中第$i$行输出$k=i$的答案。


样例

样例输入1:

10 3
4 6 7

样例输出1:

4
4
1
1

样例输入2:

5 1
8

样例输出2:

2
3


数据范围与提示

技术图片


题解

先来解释一下题意(考试的时候读了半个小时题才看懂……),这到题是要求$[1,n]$中有多少个数是$a_1\sim a_m$中$0$个数的约数,$1$个数的约数……

那么考虑我们应该怎么做。

我们可以只枚举$1\sim \sqrt{a_i}$就可以得出$a_i$的所有约数,考虑怎么存储。

我的方法是使用$map$,存储每一个约数是$a_1\sim a_i$中几个数的约数。

然后我们直接存储答案,设数组$sum[j]$表示$a_1\sim a_i$中是其中$j$个数的约数的个数。

每当扫到一个约数的时候只需要将$sum[mp[j]]--;mp[j]++;sum[mp[j]]++$即可。

时间复杂度:$\Theta(m\times \sqrt{a_i})$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,m;
int sum[201];
map<int,int> mp;
int main()
{
	scanf("%d%d",&n,&m);
	sum[0]=n;
	for(int i=1;i<=m;i++)
	{
		int x;scanf("%d",&x);
		for(int j=1;j*j<=x&&j<=n;j++)
			if(!(x%j))
			{
				sum[mp[j]]--;
				mp[j]++;
				sum[mp[j]]++;
				if(j*j!=x&&x/j<=n)
				{
					sum[mp[x/j]]--;
					mp[x/j]++;
					sum[mp[x/j]]++;
				}
			}
	}
	for(int i=0;i<=m;i++)printf("%d\n",sum[i]);
	return 0;
}

rp++

[CSP-S模拟测试]:Divisors(数学)

标签:时间   san   区间   题意   $0   viso   数据   space   The   

原文地址:https://www.cnblogs.com/wzc521/p/11622651.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!