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


    题目描述

      给定$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_1sim a_m$中$0$个数的约数,$1$个数的约数……

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

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

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

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

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

    时间复杂度:$Theta(m imes 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
    ",sum[i]);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    P1242 新汉诺塔(hanio)
    P2878 [USACO07JAN]保护花朵Protecting the Flowers
    P2096 最佳旅游线路
    [P1363] 幻想迷宫
    在矩阵上跑最小生成树
    tarjan+topsort
    tarjan缩点
    【P3398]】仓鼠找sugar
    树形数组暴力
    解决跨域问题
  • 原文地址:https://www.cnblogs.com/wzc521/p/11622651.html
Copyright © 2020-2023  润新知