【筛选法】欧教发糖

来源:互联网 发布:阿里云 弹性ip bgp带宽 编辑:程序博客网 时间:2024/06/04 23:29
【问题描述】话说自从欧教给乐乐发了一个棒棒糖之后,机房的众基友就心理不平衡了。于是欧教不得不买了很多糖准备发给众基友。但是新的问题出现了:每个基友都想得到更多的糖,因此平均分配的原则在这里根本行不通。于是欧教又在网上找了一套呵呵难度的题并出了相当坑爹的数据,以考试的成绩来作为发糖的标准。当然,欧教的发糖标准也非常奇葩:对于基友A,如果在其他基友中有t 个人的得分是A 得分的因数,则就给A 发t 个糖。现在,欧教已经测出了每个基友的得分,他想知道每个基友能得到多少颗糖。【输入数据】第一行一个整数n,表示机房一共有n 个基友。接下来共n 行,每行一个整数Bi 表示第i 个人的得分。【输出数据】共 n 行,第i 行表示第i 人得到的糖数。【样例输入】222【样例输出】11【数据范围及约定】1≤n≤100000;1≤Bi≤1000000。
此题考察筛选法的应用。
用一个cnt数组记录每个结点包含自身的约数个数,然后用筛选法的思想,每次用当前的数去筛比它大的所有数(当然被筛的数必定是这个数的倍数),最后输出时排除掉自身即可。

另外在筛的时候,先将所有的数排序可以更快(将所有相同的数放在一起筛)。
Accode:
#include <cstdio>#include <cstdlib>#include <algorithm>#include <string>const int maxN = 100010, maxP = 1000010;int cnt[maxP], a[maxN], c[maxN], n, Lim;inline int getint(){    int res = 0; char tmp;    while (!isdigit(tmp = getchar()));    do res = (res << 3) + (res << 1) + tmp - '0';    while (isdigit(tmp = getchar()));    return res;}int main(){    freopen("candy.in", "r", stdin);    freopen("candy.out", "w", stdout);    n = getint();    for (int i = 0; i < n; ++i)        Lim = std::max(Lim, a[i] = c[i] = getint());    std::sort(c, c + n);    for (int i = 0; i < n; ++i)    {        int tot = 1;        while (c[i] == c[i + 1])            ++tot, ++cnt[c[i++]];        ++cnt[c[i]];        for (int tmp = c[i] << 1; tmp             < Lim + 1; tmp += c[i])            cnt[tmp] += tot;    }    for (int i = 0; i < n; ++i)        printf("%d\n", cnt[a[i]] - 1);    return 0;}


原创粉丝点击