Bzoj4176 Lucas的数论

Description

去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了。

在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数。他现在长大了,题目也变难了。
求如下表达式的值:
 
其中 表示ij的约数个数。
他发现答案有点大,只需要输出模1000000007的值。

Input

第一行一个整数n。

Output

 一行一个整数ans,表示答案模1000000007的值。

Sample Input

2

Sample Output

8

HINT

 对于100%的数据n <= 10^9。

 

数学问题 莫比乌斯反演 脑洞题

 

$ans(n)=\sum_{i=1}^{n} \sum_{j=1}^{n} f(i,j)$
$=\sum_{i=1}^{n} \sum_{j=1}^{n} \sum_{k=1}^{n^2} [\frac{k}{gcd(i,j)}|j]$
(枚举gcd)
$=\sum_{d=1}^{n} d \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} [k|j][gcd(k,i)=1] $
(消掉j)
$=\sum_{d=1}^{n} d \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} d \lfloor \frac{n}{dk} \rfloor [gcd(k,i)=1] $
(约掉一个d)
$=\sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} \lfloor \frac{n}{k} \rfloor [gcd(k,i)=1] $

$=\sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} \lfloor \frac{n}{k} \rfloor \sum_{t|(ik)} \mu(t)$

$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{dt} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{dt} \rfloor} \lfloor \frac{n}{kt} \rfloor$
(注意到i对后面没有影响,把求和变为乘)
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{n} \lfloor \frac{n}{dt} \rfloor\sum_{k=1}^{\lfloor \frac{n^2}{dt} \rfloor} \lfloor \frac{n}{kt} \rfloor$
(注意到d在大于$ \lfloor \frac{n}{t} \rfloor$ 时,后面全是0,所以缩小求和上界,后面的k同理)
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{dt} \rfloor\sum_{k=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{kt} \rfloor$


$= \sum_{t=1}^{1} \mu(t) (\sum_{d=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{dt} \rfloor)^2 $

$\mu$的前缀和可以用bzoj3944的方法筛出来,后面的平方项可以分块计算。
也就是说分块套分块就可以愉快地出解了。

隔壁Sfailsth告诉我可以直接用Bzoj3994的结论来做
↓也就是从这个式子开始:
$\sum_{i=1}^{N}\sum_{j=1}^{M}d(ij)=\sum_{i=1}^{N}\sum_{j=1}^{M}\lfloor\frac{N}{i}\rfloor\lfloor\frac{M}{j}\rfloor\lbrack gcd(i,j)=1 \rbrack $
确实很方便

 

 

(做完这道题之后,陪伴了我们一年的权限号过期了)

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<map>
 7 #define LL long long
 8 using namespace std;
 9 const int mod=1e9+7;
10 const int mxn=5000010;
11 int read(){
12     int x=0,f=1;char ch=getchar();
13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 int pri[mxn],mu[mxn],cnt=0;
18 bool vis[mxn];
19 void init(){
20     mu[1]=1;
21     for(int i=2;i<mxn;i++){
22         if(!vis[i]){
23             pri[++cnt]=i;
24             mu[i]=-1;
25         }
26         for(int j=1;j<=cnt && (LL)pri[j]*i<mxn;j++){
27             int tmp=pri[j]*i;
28             vis[tmp]=1;
29             if(i%pri[j]==0){vis[tmp]=1;mu[tmp]=0;break;}
30             mu[tmp]=-mu[i];
31         }
32     }
33     for(int i=2;i<mxn;i++){mu[i]=mu[i-1]+mu[i];}
34     return;
35 }
36 map<int,LL>mpmu;
37 int F(int x){
38     if(x<mxn)return mu[x];
39     if(mpmu.count(x))return mpmu[x];
40     int res=1;
41     for(int i=2,pos;i<=x;i=pos+1){
42         int y=x/i;
43         pos=x/y;
44         res=((LL)res-(LL)(pos-i+1)*F(y)%mod+mod)%mod;
45     }
46     mpmu[x]=res;
47     return res;
48 }
49 int calc(int x){
50     int res=0;
51     for(int i=1,pos;i<=x;i=pos+1){
52         int y=x/i;
53         pos=x/y;
54         res=(res+(pos-i+1)*(LL)y%mod)%mod;
55     }
56     return (LL)res*res%mod;
57 }
58 int main(){
59     init();
60     int n=read();
61     LL ans=0;
62     for(int i=1,pos;i<=n;i=pos+1){
63         int y=n/i;pos=n/y;
64         ans=((LL)ans+(((LL)F(pos)-F(i-1)%mod))*calc(y)%mod)%mod;
65     }
66     ans=(ans%mod+mod)%mod;
67     printf("%lld\n",ans);
68     return 0;
69 }

 

 

 

 

posted @ 2017-06-03 19:54  SilverNebula  阅读(513)  评论(0编辑  收藏  举报
AmazingCounters.com