题目描述
给定$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++
原文地址:https://www.cnblogs.com/wzc521/p/11622651.html
时间: 2024-10-08 02:48:12