Divisors
给定\(m\)个不同的正整数\(a_1,a_2,...,a_m\),请对\(0\)到\(m\)每一个\(k\)计算,在区间\([1,n]\)里有多少正整数是\(a\)中恰好\(k\)个数的约数。
Input
第一行包含两个正整数\(n, m\),分别表示区间范围以及\(a\)数组的大小。
第二行包含\(m\)个不同的正整数\(a_1,a_2, ..., a_m\),表示\(a\)数组。Output
输出\(m+1\)行,每行一个整数,其中第\(i\)行输出\(k=i\)的答案。
Example
输入 #1
\(10\) \(3\)
\(4\) \(6\) \(7\)输出 #1
\(4\)
\(4\)
\(1\)
\(1\)输入 #2
\(5\) \(1\)
\(8\)输出 #2
\(2\)
\(3\)Scoring
测试点编号 | \(m\) | \(n,a_i\) |
---|---|---|
\(1\) | \(=5\) | \(≤1000\) |
\(2\) | \(=50\) | \(≤1000\) |
\(3\) | \(=200\) | \(≤1000\) |
\(4\) | \(=1\) | \(≤10^9\) |
\(5\) | \(=1\) | \(≤10^9\) |
\(6\) | \(=1\) | \(≤10^9\) |
\(7\) | \(=200\) | \(≤10^9\) |
\(8\) | \(=200\) | \(≤10^9\) |
\(9\) | \(=200\) | \(≤10^9\) |
\(10\) | \(=200\) | \(≤10^9\) |
题目有点绕,看了好半天
昨天这套题做的太草了
暴力枚举\(1\)到\(n\)每个数,看看它是\(a\)里几个数的约数
复杂度\(O(nm)\)
因为只有一个\(a_i\),所以枚举\(a_i\)的约数,这些是\(k=1\)时的答案,剩下的就是\(k=0\)的
复杂度\(O(\sqrt{a_i})\)
看一下数据范围,\(n\)跟\(a_i\)都太大了开不起数组,所以大概率对\(m\)下手
可以把每个\(a_i\)的约数全部求出来,然后sort,这样所有相同的约数都会挤在一起
然后扫一遍统计个数,放到数组ans里(ans[i] == x
表示能被\(a\)数组中\(i\)个数整除的数有\(x\)个
以样例1为例:
4的约数:1,2,4,6的约数:1,2,3,6,7的约数:1,7
把这堆数排序之后:1,1,1,2,2,3,4,6,7
有3个1,ans[3]++
,2个2,ans[2]++
,1个3,ans[1]++
,以此类推
最后用\(n\)减去\(\sum_{i=1}^n{ans_i}\)就是ans[0]了
贴代码(不是我的):
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1e7 + 3;
int cnt , k[MAXN] , m , x , n;
int ans[203];
int main(){
scanf( "%d%d" , &n , &m );
for( int i = 1 ; i <= m ; i ++ ){
scanf( "%d" , &x );
for( int j = 1 ; j * j <= x ; j ++ ){//找出x的因数放到k数组里
if( x % j == 0 ){
k[++cnt] = x / j;
k[++cnt] = j;
}
if( j * j == x)
cnt --;
}
}
sort( k + 1 , k + cnt + 1 );
int i = 2 , last = k[1] , tot = 1;
while( i <= cnt && k[i] <= n ){//扫一遍队列
if( k[i] != last ){//不一样了
ans[tot] += 1;//停止计算
last = k[i];//重新开始
tot = 1;
}
else tot ++;
i ++;
}
ans[tot] += 1;//不要漏掉
int sum = 0;
for( int i = 1 ; i <= m ; i ++ )
sum += ans[i];
printf( "%d" , n - sum );//算ans[0]
for( int i = 1 ; i <= m ; i ++ )
printf( "\n%d" , ans[i] );
return 0;
}
闲话:
昨天爆零了,口区
A题C题MLE,B题传文件的时候系统自动给我重命名了,导致测评姬找不到文件,不知道为啥
A题(就是这题)的MLE还是因为我检查的时候脑子抽了给数组多安了一个0,然后C题是算错
不然预计得分100+40+40
底层群众不敢重测,加上到现在oj上题目都没有放上去,所以也不知道几分不敢乱贴(虽然也没人看),从别人博客转了一个代码过来,批注是自己加工的
参考博客链接:https://blog.csdn.net/weixin_43823476/article/details/87308177
最后是关于计算ans[0]的问题,我自己想出来的做法是在约数放进数组之后,在数组中再添加\(1\)~\(n\)的数各一个,最后统计时把ans[tot]++
改成ans[tot-1]++
,效果应该一样但是绕了个大弯orz
原文:https://www.cnblogs.com/Sheffield/p/13489767.html