【問題描述】話說自從歐教給樂樂發了一個棒棒糖之後,機房的眾基友就心理不平衡了。於是歐教不得不買了很多糖準備發給眾基友。但是新的問題出現了:每個基友都想得到更多的糖,因此平均分配的原則在這雷根本行不通。於是歐教又在網上找了一套呵呵難度的題並出了相當坑爹的資料,以考試的成績來作為發糖的標準。當然,歐教的發糖標準也非常奇葩:對於基友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;}