【BZOJ】【2005】【NOI2010】能量采集

本文详细介绍了欧拉函数的概念及其在解决特定数学问题中的应用,通过引用贾志鹏教授的论文《线性筛法与积性函数》,深入探讨了如何利用线性筛法高效计算欧拉函数值,并通过具体例题演示了其实际操作过程。此外,文章还提供了C++代码实现,展示了从理论到实践的完整步骤。

欧拉函数


  玛雅,我应该先看看JZP的论文的……贾志鹏《线性筛法与积性函数》例题一

  这题的做法……仔细想下可以得到:$ans=2*\sum_{a=1}^n\sum_{b=1}^m gcd(a,b)-n*m$

  那么重点就在于算$\sum_{a=1}^n\sum_{b=1}^m gcd(a,b)$这个东西


 

copy一下JZP的推导过程:

$$ \begin{aligned}  \sum_{a=1}^n \sum_{b=1}^m gcd(a,b) &= \sum_{a=1}^n \sum_{b=1}^m \sum_{d|gcd(a,b)} \varphi(d)  \\ &= \sum_{a=1}^n \sum_{b=1}^m \sum_{d|a and d|b} \varphi(d) \\ &= \sum \varphi(d) \sum_{1 \leq a \leq n  \&\&  d|a} \sum_{1 \leq b \leq m  \&\&  d|b} 1 \\ &= \sum \varphi(d) ( \sum_{1 \leq a \leq n \&\&  d|a} 1) * ( \sum_{1 \leq b \leq m \&\& d|b} 1) \\ &= \sum \varphi(d) \left\lfloor \frac{n}{d} \right\rfloor \left\lfloor \frac{m}{d} \right\rfloor \end{aligned} $$

 1 /**************************************************************
 2     Problem: 2005
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:40 ms
 7     Memory:2152 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2005
11 #include<cstdio>
12 #include<cstring>
13 #include<cstdlib>
14 #include<iostream>
15 #include<algorithm>
16 #define rep(i,n) for(int i=0;i<n;++i)
17 #define F(i,j,n) for(int i=j;i<=n;++i)
18 #define D(i,j,n) for(int i=j;i>=n;--i)
19 using namespace std;
20 typedef long long LL;
21 inline int getint(){
22     int r=1,v=0; char ch=getchar();
23     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
24     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
25     return r*v;
26 }
27 const int N=1e5+10,INF=~0u>>2;
28 /*****************template**********************/
29 int phi[N],prime[N],tot,n,m;
30 bool check[N];
31 void getphi(int n){
32     memset(check,0,sizeof check);
33     phi[1]=1;
34     int tot=0;
35     F(i,2,n){
36         if(!check[i]){
37             prime[++tot]=i;
38             phi[i]=i-1;
39         }
40         F(j,1,tot){
41             if(i*prime[j]>n) break;
42             check[i*prime[j]]=1;
43             if(i%prime[j]==0){
44                 phi[i*prime[j]]=phi[i]*prime[j];
45                 break;
46             }
47             else phi[i*prime[j]]=phi[i]*(prime[j]-1);
48         }
49     }
50 }
51 int main(){
52     n=getint(); m=getint();
53     if (n>m) swap(n,m);
54     getphi(N-1);
55     LL ans=0;
56     F(i,1,n)
57         ans+=(LL)phi[i]*(n/i)*(m/i);
58     printf("%lld\n",ans*2-(LL)n*m);
59     return 0;
60 }
View Code

 

转载于:https://www.cnblogs.com/Tunix/p/4390681.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值