HDU 5528【2015长春现场赛 B】 Count a * b

http://acm.hdu.edu.cn/showproblem.php?pid=5528

题意

读入m,求

n|m1in1jn[ni×j]

题解

n|m1in1jn[ni×j]=n|m1in(ngcd(n,i))=n|m(n21ingcd(n,i))=n|m(n2d|n(ϕ(nd)×d))=n|mn2n|md|n(ϕ(nd)×d))

下面化简
n|md|n(ϕ(nd)×d))=d|nn|m(ϕ(nd)×d))n=eded|me|md=d|me|md(ϕ(e)×d))=d|mde|mde

d|nϕ(d)=n ,故
=d|md×md=d|mm=n|mm

故原式
=n|mn2n|mm=n|m(n2m)

注意:此题求约数不能用 n 的写法

code

#include 
#include 
#include 

typedef unsigned long long LL;

const int maxp = 50010;
const int maxn = 100010;

int n;

int prime[maxp], prime_N;
bool isprime[maxn];
void gen(int n) {
    prime_N = 0;
    memset(isprime, 1, sizeof isprime);

    isprime[0] = isprime[1] = 0;
    for (int i = 2; i < n; ++ i) {
        if (isprime[i]) prime[prime_N ++] = i;

        for (int j = 0, k; j < prime_N && (k = i*prime[j]) < n; ++ j) {
            isprime[k] = 0;
            if (!(i%prime[j]))
                break;
        }
    }
}
int pri[maxp], pri_num[maxp], pri_N;
void get_pri(int n) {
    pri_N = 0;
    for (int i = 0, p; (p = prime[i])*p <= n; ++ i) if (n%p == 0) {
        pri[pri_N] = p; pri_num[pri_N] = 0;
        while (n%p == 0) { n /= p; ++ pri_num[pri_N]; }
        ++ pri_N;
    }
    if (n > 1) { pri[pri_N] = n; pri_num[pri_N] = 1; ++ pri_N; }
}
LL res;
void dfs_divisor(int d, int div) {
    if (d == pri_N) {
        res = res + ((LL)div*div - n);
        return;
    }
    for (int i = 0; i <= pri_num[d]; ++ i) {
        dfs_divisor(d+1, div);
        div = div * pri[d];
    }
}

void solve() {
    scanf("%d", &n);
    get_pri(n);

    res = 0;
    dfs_divisor(0, 1);
    printf("%I64u\n", res);
}

int main() {
//  freopen("1002.in", "r", stdin);

    gen(100000);
    int kase; scanf("%d", &kase);
    while (kase --) solve();

//  for(;;);
    return 0;
}

你可能感兴趣的:(数论)