hdu 6134 Battlestation Operational mobius反演

给你一个n 让你计算 F(n)=ni=1ij=1ij[gcd(i,j)==1]

考虑 g(i)=ij=1ij,h(i)=ij=1ij[gcd(i,j)==1],f(n)=ni=1h(i)

显然有:
g(i)=d|ih(id)
由反演可得:

h(i)=d|iu(d)g(id)

所以如果我们得到了g(i) ,很容易就可以求出h(i),处理前缀和就得到f(i)。

所以问题就是如何求g(i),

所以这里采取枚举j的做法,
有g[j]=1,g[j+1,j∗2]=2,g[j∗2+1,j∗3]=3,…,g[j∗k+1,n]=k+1
转化一下,就是
g[j,n]+=1,g[j+1,n]+=1,g[j∗2+1,n]+=1,…,g[j∗k+1,n]+=1
所以在每个+1开始的位置加上1,然后前缀和处理一下就行了

#include<bits/stdc++.h>

using namespace std;
const int N = 1e6+5;
const int MOD = 1e9+7;
typedef long long ll;


int n;
ll g[N],f[N];
int mu[N],prime[N],vis[N],cnt;
void Init()
{
    memset(vis,0,sizeof(vis));
    mu[1] = 1;
    cnt = 0;
    for(int i=2; i<N; i++)
    {
        if(!vis[i])
        {
            prime[cnt++] = i;
            mu[i] = -1;
        }
        for(int j=0; j<cnt&&i*prime[j]<N; j++)
        {
            vis[i*prime[j]] = 1;
            if(i%prime[j]) mu[i*prime[j]] = -mu[i];
            else
            {
                mu[i*prime[j]] = 0;
                break;
            }
        }
    }
}

int main(){
    Init();
    for(int i=1;i<N;i++){
        g[i]++;
        for(int j=i;j<N;j+=i) g[j+1]++;
    }
    for(int i=1;i<N;i++) g[i]+=g[i-1];

    for(int i=1;i<N;i++)
        for(int j=i;j<N;j+=i)
            f[j]=(f[j]+mu[i]*g[j/i])%MOD;

    for(int i=1;i<N;i++) f[i]=(f[i]+f[i-1])%MOD;

    while(~scanf("%d",&n)) printf("%lld\n",f[n]);

    return 0;
}
Marcus-Bao CSDN认证博客专家 推荐系统 ACM算法竞赛 机器学习
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页
实付 59.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值