【筛选法】欧教发糖

【问题描述】
话说自从欧教给乐乐发了一个棒棒糖之后,机房的众基友就心理不平衡了。于是欧教不得不买了很多糖准备发给众基友。
但是新的问题出现了:每个基友都想得到更多的糖,因此平均分配的原则在这里根本行不通。于是欧教又在网上找了一套呵呵难度的题并出了相当坑爹的数据,以考试的成绩来作
为发糖的标准。
当然,欧教的发糖标准也非常奇葩:对于基友A,如果在其他基友中有t 个人的得分是A 得分的因数,则就给A 发t 个糖。
现在,欧教已经测出了每个基友的得分,他想知道每个基友能得到多少颗糖。
【输入数据】
第一行一个整数n,表示机房一共有n 个基友。
接下来共n 行,每行一个整数Bi 表示第i 个人的得分。
【输出数据】
共 n 行,第i 行表示第i 人得到的糖数。
【样例输入】
2
2
2
【样例输出】
1
1
【数据范围及约定】
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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值