hdu6134 Battlestation Operational 莫比乌斯第一种形式

/**
题目:hdu6134 Battlestation Operational
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6134
题意:f(n) = sigma[1<=i<=n]sigma[1<=j<=i]ceil[i/j] (gcd(i,j)==1)
给定一个n,求f(n);
思路:
公式: n = sigma[d|n]phi[d] = sigma[d|n]phi[n/d]; phi[x]表示<=x的数与x互质的个数。
证明: gcd(i,n)==d => gcd(i/d,n/d)=1; 那么和n最大公约数为d的个数为phi[n/d]; 所以n = sigma[d|n]phi[n/d] = sigma[d|n]phi[d];

根据n = sigma[d|n]phi[d];
那么有定义:
h(i)表示sigma[1<=j<=i]ceil[i/j] (gcd(i,j)==1)  这里的j都是和i互质时候计算的结果。
g(i)表示sigma[1<=j<=i]ceil[i/j]

那么h(i) = sigma[d|i]mu[d]*g(i/d);

计算所有的g(d)(1<=d<=n)通过枚举j跳在d中跳的方式处理出来,然后前缀和(也可以直接计算出来。不需要再求前缀和,具体看代码)

计算出来所有的h(i)。f(i) = sigma[1<=j<=i]h(j);

*/

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e6+10;
const int mod = 1e9 + 7;
LL f[N], g[N], h[N];
int prime[N], tot, not_prime[N];
int mu[N];
void mobius()
{
    mu[1] = 1;
    tot = 0;
    for(int i = 2; i < N; i++){
        if(!not_prime[i]){
            prime[++tot] = i;
            mu[i] = -1;
        }
        for(int j = 1; prime[j]*i<N; j++){
            not_prime[prime[j]*i] = 1;
            if(i%prime[j]==0){
                mu[prime[j]*i] = 0;
                break;
            }
            mu[prime[j]*i] = -mu[i];
        }
    }
}
void init()
{
    for(int i = 1; i < N; i++){
        g[i]++;
        for(int j = i+1; j < N; j+=i){
            g[j]++;
        }
    }
    for(int i = 1; i < N; i++) g[i] = (g[i]+g[i-1])%mod;

    for(int i = 1; i < N; i++){
        for(int j = i; j < N; j+=i){
            h[j] = (h[j]+mu[i]*g[j/i]%mod+mod)%mod;
        }
    }
    for(int i = 1; i < N; i++){
        f[i] = (f[i-1]+h[i])%mod;
    }
}
int main()
{
    int n;
    mobius();
    init();
    while(scanf("%d",&n)==1)
    {
        printf("%lld\n",f[n]);
    }
    return 0;
}

 

posted on 2017-08-17 19:55  hnust_accqx  阅读(184)  评论(0编辑  收藏  举报

导航