给定 m 个不同的正整数 a1; a2; …..; am,请对 0 到 m 每一个 k 计算,在区间 [1; n] 里有多少正整数是 a 中恰好 k 个数的约数
Input 
第一行包含两个正整数 n;m,分别表示区间范围以及 a 数组的大小。 
第二行包含 m 个不同的正整数 a1; a2; …….; am,表示 a 数组。
Output 
输出 m + 1 行,每行一个整数,其中第 i 行输出 k = i 的答案。
Examples 
div.in 
10 3 
4 6 7
div.out 
4 
4 
1 
1
分析: 
区间 [1,n] 里有多少正整数是 a 中恰好 k 个数的约数 
乍一看这个条件,懵了。。。 
第一个想法(也是正确的想法)就是把a中的数分解一下约数, 
然而zz的我在考场上明知道10^9的数组开不下, 
然而我就把约数的大小作为数组下标,当有一个数有x的约束时,a[x]++ 
这样查询时O(1)出解,然而有又什么用呢,稳稳30
实际上m的范围不大,所有数的约数总和超不过100000, 
这样我们只需要储存一下约数的大小, 
sort一下,累计一下每一个约数在a数组中重复了多少次, 
记录就可以了, 
对于0的处理:记录一下出现了多少数字(tot),输出n-tot
这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1001;
int n,m,mx;
int a[100010],tot=0;
int ans[100010];
int max(int x,int y)
{
    if (x>y) return x;
    else return y;
}
inline void doit(int x)
{
    int i;
    mx=0;
    for (i=1;x/i>=i;i++)
        if (x%i==0)
        {
            a[++tot]=i;   //记录因数 
            a[++tot]=x/i;
            if (i==x/i) tot--;
        }
    return;
}
int main()
{
    freopen("div.in","r",stdin);  
    freopen("div.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int u;
        scanf("%d",&u);
        doit(u);
    }
    sort(a+1,a+tot+1);
    int j=a[1],tt=0,t=0,i=1;
    do
    {
        tt=0;
        while (a[i]==j&&j<=n) tt++,i++;
        ans[tt]++;
        t++;  //出现过的数字++ 
        j=a[i];
    }while (i<=tot&&j<=n);
    printf("%d
",n-t);
    for (int i=1;i<=m;i++)
        printf("%d
",ans[i]);
    return 0;
}