hdu6134 Battlestation Operational【2017多校第八场】

转载请注明出处,谢谢http://blog.csdn.net/bigtiao097?viewmode=contents

题意

求f (n)mod109+7,(1n106)

f(n)=i=1nj=1iij[(i,j)=1]

where [(i,j)=1] evaluates to be 1 if gcd(i,j)=1 , otherwise 0.

思路

f(n)=i=1nni[(n,i)=1]

g(n)=i=1nni

打表找规律能得到
g(n)=d|nf(d)

这个式子当时同学打表找规律得到的,等证明出来再来更新
然后由莫比乌斯反演我们可以得到
f(n)=d|nμ(nd)g(d)

现在问题转化成了怎么求 g(n)
一种方法就是分段优化,对于每个n可以 O(n) 求出来,这样总体的复杂度就是 O(nn) ,显然会超时。。。
下面介绍怎么正确求 g(n)
递推法
g(n)=1+g(n1)+τ(n1)

关于这个递推式可以看一下 这里
τ(x) 表示x的因子个数
τ(x) 这个函数可以 O(nlogn) 求出,这个和求因子和的过程差不多,具体可以看代码
然后就可以 O(n) 的求 g(n) ,
然后就能 O(nlogn) 的求出 f(n) 了,这样就结束了
注:下面代码中的f(n)与g(n)正好与上面思路中相反


具体代码如下:
Result:Accepted     Memory: 30392K     Time : 374MS

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const int mod = 1e9+7;
ll sigma[maxn];
ll f[maxn];
ll g[maxn];
ll tau[maxn];
ll n,ans,cur;
bool vis[maxn];
int prime[maxn];
int mu[maxn];
int tot;
void mobius()
{
    memset(vis,0,sizeof vis);
    mu[1] = 1;
    tot = 0;
    for(int i=2;i<maxn;i++)
    {
        if( !vis[i] ){
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < tot; j++)
        {
            if(i * prime[j] >=maxn) break;
            vis[i * prime[j]] = true;
            if( i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
                mu[i * prime[j]] = -mu[i];
        }
    }
}
void init()
{
    mobius();
    for(int i=1;i<maxn;i++)
        for(int j=i;j<maxn;j+=i)
            tau[j]++;
    f[1] = 1;
    for(int i=2;i<maxn;i++)
        f[i] = 1+f[i-1]+tau[i-1];
    for(int i=1;i<maxn;i++)
        for(int j=i;j<maxn;j+=i)
            g[j] = (g[j]+mu[j/i]*f[i]%mod+mod)%mod;
    for(int i=2;i<maxn;i++)
        g[i] = (g[i-1]+g[i])%mod;
}
int main()
{
    init();
    while(~scanf("%lld",&n))
        printf("%lld\n",g[n]);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值