这个之前推过,没去实现。。

也是将lcm转成gcd做,然后枚举gcd,可得

bzoj2154(莫比乌斯函数+积性函数)_积性函数

然后换元一下,令d=dd',枚举dd',可得

bzoj2154(莫比乌斯函数+积性函数)_#define_02

然后主要是处理d'的求和了,由于是因子和,所以可以猜想这个求和本身也是积性函数,那么只要dμ(d)是积性函数就可以了。。

设f(n)=nμ(n),n与m互质,f(nm)=nmμ(nm)=nmμ(n)μ(m)=f(n)(m),故f(n)为积性函数


bzoj2154(莫比乌斯函数+积性函数)_积性函数_03

,符合狄利克雷卷积形式,故g(n)也为积性函数而

bzoj2154(莫比乌斯函数+积性函数)_#include_04

故可以线性预处理g(n)

然后就可以变成

bzoj2154(莫比乌斯函数+积性函数)_积性函数_05

然后就可以分块求了。。

尝试过线性筛的时候直接把上面的和式也求了,不过取模太多次貌似变慢了不少。。。还是分块大法吼。。。

 

 

 

/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid ((x+y)/2)
#define NM 10000005
#define nm 10005
#define N 1000005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const ll inf=20101009;
using namespace std;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}





ll a[NM],ans,inv[10];
int n,m,g[NM],prime[NM],tot;
bool v[NM];

void init(){
inv[1]=g[1]=a[1]=1;
inc(i,2,4)inv[i]=inv[inf%i]*(inf-inf/i)%inf;
inc(i,2,n){
if(!v[i])prime[++tot]=i,g[i]=1-i;
inc(j,1,tot){
if(i*prime[j]>n)break;
v[i*prime[j]]++;
if(i%prime[j]==0){g[i*prime[j]]=g[i];break;}
g[i*prime[j]]=g[i]*(1-prime[j]);
}
a[i]=(a[i-1]+(ll)g[i]*i%inf+inf)%inf;
}
}


int main(){
n=read();m=read();
init();
if(n>m)swap(n,m);
for(int i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
ans+=(a[j]-a[i-1]+inf)%inf*(n/i)%inf*(m/i)%inf*(n/i+1)%inf*(m/i+1)%inf*inv[4]%inf;ans%=inf;
}
return 0*printf("%lld\n",ans);
}

 

 

2154: Crash的数字表格

Time Limit: 20 Sec  Memory Limit: 259 MB
Submit: 5891  Solved: 2137
[​​​Submit​​​][​​Status​​​][​​Discuss​​]

Description

今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数。例如,LCM(6, 8) = 24。回到家后,Crash还在想着课上学的东西,为了研究最小公倍数,他画了一张N*M的表格。每个格子里写了一个数字,其中第i行第j列的那个格子里写着数为LCM(i, j)。一个4*5的表格如下: 1 2 3 4 5 2 2 6 4 10 3 6 3 12 15 4 4 12 4 20 看着这个表格,Crash想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当N和M很大时,Crash就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash只想知道表格里所有数的和mod 20101009的值。

Input

输入的第一行包含两个正整数,分别表示N和M。

Output

输出一个正整数,表示表格中所有数的和mod 20101009的值。

Sample Input

4 5

Sample Output

122
【数据规模和约定】
100%的数据满足N, M ≤ 10^7。

HINT

 

Source

 

[​​Submit​​​][​​Status​​​][​​Discuss​​]