1.莫比乌斯函数求和
基准时间限制:3 秒 空间限制:131072 KB 分值: 320
难度:7级算法题
莫比乌斯函数,由德国数学家和天文学家莫比乌斯提出。梅滕斯(Mertens)首先使用μ(n)(miu(n))作为莫比乌斯函数的记号。具体定义如下:
如果一个数包含平方因子,那么miu(n) = 0。例如:miu(4), miu(12), miu(18) = 0。
如果一个数不包含平方因子,并且有k个不同的质因子,那么miu(n) = (-1)^k。例如:miu(2), miu(3), miu(30) = -1,miu(1), miu(6), miu(10) = 1。
给出一个区间[a,b],S(a,b) = miu(a) + miu(a + 1) + ...... miu(b)。
例如:S(3, 10) = miu(3) + miu(4) + miu(5) + miu(6) + miu(7) + miu(8) + miu(9) + miu(10)
= -1 + 0 + -1 + 1 + -1 + 0 + 0 + 1 = -1。
Input
输入包括两个数a, b,中间用空格分隔(2 <= a <= b <= 10^10)
Output
输出S(a, b)。
Input示例
3 10
Output示例
-1
①式怎么化简出来的呢?参考一个经典问题:求1~n的约数之和。除了计算每个数的贡献之外我们还能这样:
根据上面的原理就能理解①式了,于是计算M(n)就能采用递归的方法完成。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 6e6;
int mu[maxn+3], prime[maxn+3];
bool bo[maxn+3];
map<LL,LL>mp;
void get()//莫比乌斯函数打表
{
mu[1]=1;
for(int i=2; i<=maxn; ++i)
{
if(!bo[i])
{
prime[++prime[0]] = i;
mu[i] = -1;
}
for(int j=1; j<=prime[0]&&prime[j]*i<=maxn; ++j)
{
bo[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=1; i<=maxn; ++i)
mu[i] += mu[i-1];
}
LL cal(LL n)
{
if(n<=maxn) return mu[n];
if(mp.count(n)) return mp[n];
LL ans = 0;
for(LL l=2,r; l<=n; l=r+1)//分块加速,因为n/i相同的值有很多个。
{
r=n/(n/l);
ans += (r-l+1)*cal(n/l);
}
ans = 1-ans;
mp[n] = ans;
return ans;
}
int main()
{
get();
LL a, b;
scanf("%lld%lld",&a,&b);
printf("%lld\n",cal(b)-cal(a-1));//作差即可
return 0;
}
2.欧拉函数求和
基准时间限制:3 秒 空间限制:131072 KB 分值: 320
难度:7级算法题
对正整数n,欧拉函数是小于或等于n的数中与n互质的数的数目。此函数以其首名研究者欧拉命名,它又称为Euler's totient function、φ函数、欧拉商数等。例如:φ(8) = 4(Phi(8) = 4),因为1,3,5,7均和8互质。
S(n) = Phi(1) + Phi(2) + ...... Phi(n),给出n,求S(n),例如:n = 5,S(n) = 1 + 1 + 2 + 2 + 4 = 10,定义Phi(1) = 1。由于结果很大,输出Mod 1000000007的结果。
Input
输入一个数N。(2 <= N <= 10^10)
Output
输出S(n) Mod 1000000007的结果。
Input示例
5
Output示例
10
跟上题同一个套路。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 6e6;
const LL mod = 1e9+7;
bool bo[maxn+3];
LL phi[maxn+3], prime[maxn+3], two;
map<LL,LL>mp;
LL qmod(LL a, LL b, LL c)
{
LL ans=1LL;
for(;b;b>>=1)
{
if(b&1) ans=ans*a%c;
a=a*a%c;
}
return ans;
}
void get()//欧拉函数打表
{
phi[1] = 1;
two = qmod(2, mod-2, mod);//2在该模数下的逆元
for(LL i=2; i<=maxn; ++i)
{
if(!bo[i])
{
prime[++prime[0]] = i;
phi[i] = i-1;
}
for(LL j=1; j<=prime[0]&&i*prime[j]<=maxn; ++j)
{
bo[i*prime[j]] = 1;
if(i%prime[j] == 0)
{
phi[i*prime[j]] = prime[j]*phi[i];
break;
}
else phi[i*prime[j]] = (prime[j]-1)*phi[i];
}
}
for(int i=1; i<=maxn; ++i)//欧拉函数前缀和
phi[i] = (phi[i-1]+phi[i])%mod;
}
LL cal(LL n)
{
if(n<=maxn) return phi[n];
if(mp.count(n)) return mp[n];
LL ans = 0;
for(LL l=2,r; l<=n; l=r+1)//分块加速,因为n/i相同的值有很多个。
{
r=n/(n/l);
ans += (r-l+1)%mod*cal(n/l)%mod;
ans %= mod;
}
ans = (((n%mod*((n+1)%mod)%mod*two%mod-ans)%mod)+mod)%mod;
mp[n] = ans;
return ans;
}
int main()
{
get();
LL n;
scanf("%lld",&n);
printf("%lld\n",cal(n));
return 0;
}
3.HDU5608 function
Problem Description
There is a function
f(x),which is defined on the natural numbers set
N,satisfies the following eqaution
N2−3N+2=∑d|Nf(d)
calulate ∑Ni=1f(i) mod 109+7.
N2−3N+2=∑d|Nf(d)
calulate ∑Ni=1f(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.
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
13
Sample Output
2$1^2-3*1+2=f(1)=0$$2^2-3*2+2=f(2)+f(1)=0->f(2)=0$$3^2-3*3+2=f(3)+f(1)=2->f(3)=2$$f(1)+f(2)+f(3)=2$
Source
# include <iostream>
# include <cstdio>
# include <map>
# include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 1e6;
map<LL,LL>mp;
LL six, two, sum[maxn+3];
int prime[maxn+3], mu[maxn+3];
bool bo[maxn+3];
LL qmod(LL a, LL b, LL c)
{
LL ans = 1;
for(;b;b>>=1)
{
if(b&1) ans=ans*a%c;
a=a*a%c;
}
return ans;
}
void pre()
{
mu[1] = 1;
for(int i=2; i<=maxn; ++i)
{
if(!bo[i])
{
prime[++prime[0]] = i;
mu[i] = -1;
}
for(int j=1; j<=prime[0]&&prime[j]*i<=maxn; ++j)
{
bo[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=1; i<=maxn; ++i)
{
for(int j=i; j<=maxn; j+=i)
{
sum[j] += mu[j/i]*((1LL*i*i-1LL*3*i+2)%mod+mod)%mod;
sum[j] = (sum[j]+mod)%mod;
}
sum[i] = (sum[i]+sum[i-1])%mod;
}
}
LL cal(LL n)
{ if(n<=maxn) return sum[n];
if(mp.count(n)) return mp[n];
LL ans = 1LL*n%mod*((n+1)%mod)%mod*((2*n+1)%mod)%mod*six%mod;
ans = (ans-n%mod*((n+1)%mod)%mod*3%mod*two%mod+mod)%mod;
ans = (ans+n*2%mod)%mod;
for(LL l=2, r; l<=n; l=r+1)
{
r = n/(n/l);
ans = (ans-(r-l+1)%mod*cal(n/l)%mod+mod)%mod;
}
mp[n] = ans;
return ans;
}
int main()
{
pre();
LL n;
int t;
six = qmod(6, mod-2, mod);
two = qmod(2, mod-2, mod);
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
printf("%lld\n",cal(n));
}
return 0;
}