bzoj2818 Gcd

Description

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对.

Input

一个整数N

Output

如题

Sample Input

4

Sample Output

4

HINT

hint
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7

 

正解:莫比乌斯函数。

这题可以用欧拉函数水过,然而我作死写了莫比乌斯。。并且这题得出的函数不是积性函数,然后就不会欧了。。

假设有$n$和$m$两个数。

$Ans=\sum_{d=1,prime}^{min(n,m)}\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=d]$

$Ans=\sum_{d=1,prime}^{min(n,m)}\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{m}{d}}[\gcd(i,j)=1]$

$Ans=\sum_{d=1,prime}^{min(n,m)}\sum_{p=1}^{min(\frac{n}{d},\frac{m}{d})}\mu(p)\left \lfloor \frac{n}{dp} \right \rfloor\left \lfloor \frac{m}{dp} \right \rfloor$

令$Q=dp$,$Ans=\sum_{d=1,prime}^{min(n,m)}\sum_{d|Q}^{min(n,m)}\mu(\frac{Q}{d})\left \lfloor \frac{n}{Q} \right \rfloor\left \lfloor \frac{m}{Q} \right \rfloor$

$Ans=\sum_{Q=1}^{min(n,m)}\left \lfloor \frac{n}{Q} \right \rfloor\left \lfloor \frac{m}{Q} \right \rfloor\sum_{d|Q}\mu(\frac{Q}{d})[d,prime]$

然后不会了。。但是后面那个函数其实是可以线性筛的。

设$g(i)=sum_{d|Q}\mu(\frac{Q}{d})[d,prime]$,当$i$为质数时,$g(i)=1$;当$i mod prime[j]=0$时,$g(i*prime[j])=\mu(i)$;当$i mod prime[j]!=0$时,$g(i*prime[j])=\mu(i)-g(i)$。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define N (10000010)
16 #define il inline
17 #define RG register
18 #define ll long long
19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
20 
21 using namespace std;
22 
23 int vis[N],mu[N],g[N],prime[N],n,cnt,pos;
24 ll ans;
25 
26 il void sieve(){
27     vis[1]=mu[1]=1;
28     for (RG int i=2;i<=n;++i){
29     if (!vis[i]) mu[i]=-1,g[i]=1,prime[++cnt]=i;
30     for (RG int j=1,k=i*prime[j];j<=cnt && k<=n;++j,k=i*prime[j]){
31         vis[k]=1;
32         if (i%prime[j]) mu[k]=-mu[i],g[k]=mu[i]-g[i];
33         else{ g[k]=mu[i]; break; }
34     }
35     }
36     for (RG int i=2;i<=n;++i) g[i]+=g[i-1]; return;
37 }
38 
39 il void work(){
40     cin>>n; sieve();
41     for (RG int i=1;i<=n;i=pos+1){
42     pos=n/(n/i);
43     ans+=(ll)(n/i)*(ll)(n/i)*(ll)(g[pos]-g[i-1]);
44     }
45     cout<<ans; return;
46 }
47 
48 int main(){
49     File("gcdprime");
50     work();
51     return 0;
52 }

 

posted @ 2017-03-18 16:14  wfj_2048  阅读(182)  评论(0编辑  收藏  举报