HDU-5608:function
Posted zxytxdy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU-5608:function相关的知识,希望对你有一定的参考价值。
HDU-5608:function
题意:
设函数(f(x))有:
[
N^2-3N+2=sum_{d|N}f(d)
]
求(sum_{i=1}^Nf(i))。
思路:
设:
[
F(n)=sum_{d|n}f(d)=n^2-3n+2
]
反演得:
[
f(n)=sum_{d|n}mu(d)F(frac{n}{d})
]
求和:
[
sum_{i=1}^Nf(i)=sum_{i=1}^Nsum_{d|i}mu(d)F(frac{i}{d})
]
将枚举(i)改为枚举(id):
[
sum_{d=1}^Nmu(d)sum_{i=1}^{frac{N}{d}}F(i)
]
我们可以发现前面的可以杜教筛一下,问题在于如何求后面的式子。
[
sum_{i=1}^Ni^2-3i+2
]
我们一项一项的拆开。
首先有平方和求和公式,然后有等差数列求和公式,最后再加个(2n),那么这个问题就解决了。
[
sum=frac{n(n+1)(2n+1)}{6}-3frac{(n+1)(n)}{2}+2n
]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e6;
const int mod = 1e9+7;
bool vis[maxn+10];
int primes[maxn+10], cnt;
ll mu[maxn+10];
void init(int n)
{
mu[1] = 1;
for(int i = 2; i <= n; i++)
{
if(!vis[i])
{
primes[++cnt] = i;
mu[i] = -1;
}
for(int j = 1; primes[j] <= n/i; j++)
{
vis[primes[j]*i] = 1;
if(i % primes[j] == 0) break;
else mu[i*primes[j]] = -mu[i];
}
}
for(int i = 1; i <= n; i++)
mu[i] += mu[i-1], mu[i] %= mod;
}
unordered_map<ll, ll> Smu;
inline ll getSmu(ll n)
{
if(n <= maxn) return mu[n];
if(Smu[n]) return Smu[n];
ll res = 1;
for(ll l = 2, r; l <= n; l = r+1)
{
r = n/(n/l);
res -= (r-l+1)%mod*getSmu(n/l)%mod;
res = (res+mod)%mod;
} return Smu[n] = res;
}
const ll inv6 = 166666668;
const ll inv2 = 500000004;
ll S(ll x)
{
ll res = 0;
res += x*(x+1)%mod*(2*x+1)%mod*inv6%mod; res %= mod;
res -= 3*(x+1)%mod*(x)%mod*inv2%mod; res %= mod;
res += 2*x%mod; res %= mod;
return res;
}
ll n;
void solve()
{
scanf("%lld", &n);
ll ans = 0;
for(ll l = 1, r; l <= n; l = r+1)
{
r = n/(n/l);
ans += ((getSmu(r)-getSmu(l-1))%mod+mod)%mod*S(n/l)%mod;
ans %= mod;
}
printf("%lld
", ans);
}
int main()
{
init(maxn);
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}
以上是关于HDU-5608:function的主要内容,如果未能解决你的问题,请参考以下文章