码迷,mamicode.com
首页 > 其他好文 > 详细

UVA11426

时间:2018-08-28 18:54:06      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:链接   for   prime   new   inline   math   www.   +=   转化   

目录

题目链接
\(T≤100\)
\(n≤40000000\)

解法一:莫比乌斯反演

打算用莫比乌斯反演水一发.
大概在
\(O(T*n*\sqrt{n})\)
UVA评测机真快,竟然过了.

#include <iostream>
#include <cstdio>
#define ll unsigned long long
const ll maxN= 40000000 + 7;

bool vis[maxN];
ll prime[maxN];
ll mu[maxN];
ll sum[maxN];

void init() {
    ll num = 0;
    vis[1] = 1;
    mu[1] = 1;
    for(ll i = 2;i <= 40000000;++ i) {
        if( !vis[i] ) {
            prime[++ num] = i;
            mu[i] = -1;
        }
        for(ll j = 1;j <= num && prime[j] * i <= 40000000;++ j) {
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    for(ll i = 1;i <= 40000000;++ i) 
        sum[i] = sum[i - 1] + mu[i];
    return;
}

ll slove(ll n,ll k) {
    ll ans = 0;
    n /= k;
    for(ll l = 1,r;l <= n;l = r + 1) {
        r = n / (n / l);
        ans += ( sum[r] - sum[l - 1] ) * (n / l) * (n / l); 
    }
    return ans;
}

int main() {
    ll n = 1;
    init();
    while(scanf("%llu",&n) && n) {  
        ll ans = 0;
        for(ll i = 1;i <= n;++ i) 
            ans += i * slove(n,i);
        printf("%llu\n",(ans - (n + 1) * n / 2) / 2);
    }
    return 0;
}

解法2:利用phi

考虑每个数\(x\)被当做\(Gcd\)对答案的贡献.
\[GCD(i,j) = x\]
转化成
\[GCD(i/x,j/x) == 1\]
这个题跟GCD差不多
我也是写了题解

#include <iostream>
#include <cstdio>
const int maxN = 40000000 + 7;

int prime[7000000];
long long phi[maxN];

void init() {
    int num = 0;
    phi[1] = 1;
    for(int i = 2;i < maxN;++ i) {
        if( !phi[i] ) {
            prime[++ num] = i;
            phi[i] = i - 1;
        }
        for(int j = 1;j <= num && prime[j] * i < maxN;++ j) {
            if(i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[i * prime[j]] =  phi[i] *( prime[j] - 1);
        }
    }   
    for(int i = 2;i < maxN;++ i) 
        phi[i] += phi[i - 1];
    return ;
}

int main() {
    int fuck = 1;
    int n;
    init();
    while(fuck) {
        scanf("%d",&n);
        if(!n) break;
        long long sum = 0;
        for(int i = 1;i < n;++ i) {
            sum += ( phi[n / i] - 1 ) * i;
        }
        printf("%lld\n",sum);
    }
    return 0;
}

UVA11426

标签:链接   for   prime   new   inline   math   www.   +=   转化   

原文地址:https://www.cnblogs.com/tpgzy/p/9549974.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!