HDU 5608 function(杜教筛)

function
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1700 Accepted Submission(s): 607

Problem Description
There is a function f(x),which is defined on the natural numbers set N,satisfies the following eqaution

N 2 − 3 N + 2 = ∑ d ∣ N f ( d ) N^2−3N+2=∑_{d|N}f(d) N23N+2=dNf(d)

calulate ∑ i = 1 N f ( i ) ∑^N_{i=1}f(i) i=1Nf(i) mod 109+7.

Input
the first line contains a positive integer T,means the number of the test cases.

next T lines there is a number N

T≤500,N≤109

only 5 test cases has N>106.

Output
Tlines,each line contains a number,means the answer to the i-th test case.

Sample Input
1
3

Sample Output
2

1 2 − 3 ∗ 1 + 2 = f ( 1 ) = 0 1^2-3*1+2=f(1)=0 1231+2=f(1)=0
2 2 − 3 ∗ 2 + 2 = f ( 2 ) + f ( 1 ) = 0 − > f ( 2 ) = 0 2^2-3*2+2=f(2)+f(1)=0->f(2)=0 2232+2=f(2)+f(1)=0>f(2)=0
3 2 − 3 ∗ 3 + 2 = f ( 3 ) + f ( 1 ) = 2 − > f ( 3 ) = 2 3^2-3*3+2=f(3)+f(1)=2->f(3)=2 3233+2=f(3)+f(1)=2>f(3)=2
f ( 1 ) + f ( 2 ) + f ( 3 ) = 2 f(1)+f(2)+f(3)=2 f(1)+f(2)+f(3)=2

题意

有这么一个函数 f ( x ) f(x) f(x)满足
N 2 − 3 N + 2 = ∑ d ∣ N f ( d ) N^2-3N+2=\sum_{d|N}f(d) N23N+2=dNf(d)
然后求
∑ i = 1 n f ( i )   m o d   1 0 9 + 7 \sum_{i=1}^nf(i)\ mod\ 10^9+7 i=1nf(i) mod 109+7

思路

g ( n ) = n 2 − 3 n + 2 g(n)=n^2-3n+2 g(n)=n23n+2
那么有 g ( n ) = ( I ∗ f ) ( n ) g(n)=(I*f)(n) g(n)=(If)(n)
左边是恒等函数 I I I f f f的狄利克雷卷积,那么根据 I ∗ μ = e I*\mu=e Iμ=e,两边再乘上一个 μ \mu μ,有
( μ ∗ g ) = ( μ ∗ I ) ∗ f (\mu*g)=(\mu*I)*f (μg)=(μI)f
( μ ∗ g ) = f (\mu*g)=f (μg)=f
所以有
f ( n ) = ∑ d ∣ n μ ( d ) g ( n d ) f(n)=\sum_{d|n}\mu(d)g(\frac{n}{d}) f(n)=dnμ(d)g(dn)
那么
∑ i = 1 n f ( n ) = ∑ i = 1 n ∑ d ∣ i μ ( d ) g ( i d ) \sum_{i=1}^nf(n)=\sum_{i=1}^n\sum_{d|i}\mu(d)g(\frac{i}{d}) i=1nf(n)=i=1ndiμ(d)g(di)
当前的含义是枚举 1 − n 1-n 1n中每一个i的因子,这个和枚举 1 − n 1-n 1n中每一个数的倍数是等价的,那么就有
∑ i = 1 n f ( n ) = ∑ d = 1 n μ ( d ) ∑ d ∣ i g ( i d ) \sum_{i=1}^nf(n)=\sum_{d=1}^n\mu(d)\sum_{d|i}g(\frac{i}{d}) i=1nf(n)=d=1nμ(d)dig(di)
∑ i = 1 n f ( n ) = ∑ d = 1 n μ ( d ) ∑ i = 1 ⌊ n d ⌋ g ( i ) \sum_{i=1}^nf(n)=\sum_{d=1}^n\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}g(i) i=1nf(n)=d=1nμ(d)i=1dng(i)
S ( n ) = ∑ i = 1 n g ( i ) S(n)=\sum_{i=1}^ng(i) S(n)=i=1ng(i)则有
S ( n ) = ∑ i = 1 n i 2 − 3 ∑ i = 1 n i + ∑ i = 1 n 2 S(n)=\sum_{i=1}^ni^2-3\sum_{i=1}^ni+\sum_{i=1}^n2 S(n)=i=1ni23i=1ni+i=1n2
S ( n ) = n ( n + 1 ) ( 2 n + 1 ) 6 − 3 n ( n + 1 ) 2 + 2 n S(n)=\frac{n(n+1)(2n+1)}{6}-3\frac{n(n+1)}{2}+2n S(n)=6n(n+1)(2n+1)32n(n+1)+2n
那么原式就有
∑ i = 1 n f ( n ) = ∑ d = 1 n μ ( d ) S ( ⌊ n d ⌋ ) \sum_{i=1}^nf(n)=\sum_{d=1}^n\mu(d)S(\left \lfloor \frac{n}{d} \right \rfloor) i=1nf(n)=d=1nμ(d)S(dn)

∑ i = 1 n f ( n ) = ∑ d = 1 n μ ( d ) ( ⌊ n d ⌋ ( ⌊ n d ⌋ + 1 ) ( 2 ⌊ n d ⌋ + 1 ) 6 − 3 ⌊ n d ⌋ ( ⌊ n d ⌋ + 1 ) 2 + 2 ⌊ n d ⌋ ) \sum_{i=1}^nf(n)=\sum_{d=1}^n\mu(d)(\frac{\left \lfloor \frac{n}{d} \right \rfloor(\left \lfloor \frac{n}{d} \right \rfloor+1)(2\left \lfloor \frac{n}{d} \right \rfloor+1)}{6}-3\frac{\left \lfloor \frac{n}{d} \right \rfloor(\left \lfloor \frac{n}{d} \right \rfloor+1)}{2}+2\left \lfloor \frac{n}{d} \right \rfloor) i=1nf(n)=d=1nμ(d)(6dn(dn+1)(2dn+1)32dn(dn+1)+2dn)
莫比乌斯函数的前缀和就可以用杜教筛求了,和函数就可以用分块来做,提前处理一下6的逆元和2的逆元就可以了

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+5;
const int mod=1e9+7;
const int inv6=166666668;
const int inv2=500000004;
bool vis[N];
int mu[N];
int prime[N];
int cnt;
void init()
{
    cnt=0;
    mu[1]=1;
    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]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            else
                mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=2;i<N;i++)
        mu[i]=mu[i-1]+mu[i];
}
unordered_map<int,int>S;
int Sum(int n)
{
    if(n<N) return mu[n];
    else if(S.find(n)!=S.end())return S[n];
    int ans=1;
    for(int i=2,last;i<=n;i=last+1)
    {
        last=n/(n/i);
        ans=ans-(last-i+1)*Sum(n/i);
    }
    S[n]=ans;
    return ans;
}

int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        long long ans=0;
        for(int i=1,last;i<=n;i=last+1)
        {
            last=n/(n/i);
            long long m=n/i;
            ans=(ans+(Sum(last)-Sum(i-1)+mod)%mod*(m*(m+1)%mod*(2*m%mod+1)%mod*inv6%mod-3*m%mod*(m+1)%mod*inv2%mod+2*m%mod+mod)%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值