Processing math: 16%

【BZOJ】【2705】【SDOI2012】Longge的问题

欧拉函数/狄利克雷卷积/积性函数


  

2705: [SDOI2012]Longge的问题

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1275  Solved: 820
[Submit][Status][Discuss]

Description

Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。

Input

一个整数,为N。

Output

一个整数,为所求的答案。

Sample Input

6

Sample Output

15

HINT

【数据范围】

对于60%的数据,0<N<=2^16。

对于100%的数据,0<N<=2^32。

 

Source

[Submit][Status][Discuss]

 

  掉到莫比乌斯反演的坑里无法自拔,问了zyf&在网上看了题解才做出来TAT……我果然好弱

  这个题是要求nx=1gcd(x,n),考虑它的实际意义,我们可以得到ans=\sum_{i|n}i*\varphi(\frac{n}{i})

  但是明显φ函数我们是没法预处理的……(\frac{n}{i}这玩意太大了),但考虑到n的约数不会太多,所以我们可以边找因数边计算φ。

复制代码
 1 /**************************************************************
 2     Problem: 2705
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:16 ms
 7     Memory:804 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2705
11 #include<cmath>
12 #include<cstdio>
13 #define F(i,j,n) for(int i=j;i<=n;i++)
14 typedef long long LL;
15 LL phi(LL n){
16     int ret=1,i;
17     for(int i=2;i*i<=n;i++){
18         if (n%i==0){
19             n/=i; ret*=i-1;
20             while(n%i==0) n/=i,ret*=i;
21         }
22     }
23     if (n>1) ret*=n-1;
24     return ret;
25 }
26 int main(){
27     int n;
28     scanf("%d",&n);
29     long long ans=0;
30     for(int i=1;i*i<=n;i++)
31         if(n%i==0){
32             ans+=(LL)i*phi(n/i);
33             if (i*i<n) ans+=(LL)n/i*phi(i);
34         }
35     printf("%lld\n",ans);
36     return 0;
37 }
View Code
复制代码

  但是其实对于这个函数\sum_{i|n} i*\varphi(\frac{n}{i})是满足积性的,因为它就是id(x)=x\varphi(x)这两个函数的狄利克雷卷积,那么……(贴个网上的图片)

复制代码
 1 /**************************************************************
 2     Problem: 2705
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:8 ms
 7     Memory:816 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2705
11 #include<cmath>
12 #include<cstdio>
13 #define F(i,j,n) for(int i=j;i<=n;i++)
14 int main(){
15     int n;
16     scanf("%d",&n);
17     long long ans=n;
18     F(i,2,sqrt(n)){
19         if(n%i==0){
20             int k=0;
21             for(k;n%i==0;k++,n/=i);
22             ans+=ans*(i-1)*k/i;
23         }
24     }
25     if (n!=1) ans+=ans*(n-1)*1/n;
26     printf("%lld\n",ans);
27     return 0;
28 }
View Code(诡异的加法版本)
复制代码

P.S.但是这个【乘起来】的过程我在网上没找到啊……写法好诡异我理解不了……所以我机(sha)智(bi)地改了一个利用快速幂的版本= =耗时居然一样……如果有哪位路过的大牛搞明白了前面那个加法版本的意思的话请留言教我一下,万分感谢。

复制代码
 1 /**************************************************************
 2     Problem: 2705
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:8 ms
 7     Memory:816 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2705
11 #include<cmath>
12 #include<cstdio>
13 #define F(i,j,n) for(int i=j;i<=n;i++)
14 typedef long long LL;
15 LL Pow(LL a,LL b){
16     LL r=1;
17     for(;b;b>>=1,a*=a)if(b&1)r*=a;
18     return r;
19 }
20 int main(){
21     int n;
22     scanf("%d",&n);
23     LL ans=1;
24     F(i,2,sqrt(n)){
25         if(n%i==0){
26             int k=0;
27             for(k;n%i==0;k++,n/=i);
28             ans*=(k+1)*Pow(i,k)-k*Pow(i,k-1);
29 //            ans+=ans*(i-1)*k/i;
30         }
31     }
32     if (n!=1) ans*=2*Pow(n,1)-1;
33     printf("%lld\n",ans);
34     return 0;
35 }
View Code(乘法版本)
复制代码

 

posted @   Tunix  阅读(282)  评论(1)    收藏  举报
编辑推荐:
· 领域模型应用
· 记一次 ADL 导致的 C++ 代码编译错误
· MySQL查询执行顺序:一张图看懂SQL是如何工作的
· 为什么PostgreSQL不自动缓存执行计划?
· 于是转身独立开发者
阅读排行:
· Cursor 1.2重磅更新,这个痛点终于被解决了!
· C#/.NET/.NET Core优秀项目和框架2025年6月简报
· 从被喷“假开源”到登顶 GitHub 热榜,这个开源项目上演王者归来!
· C#开发的Panel滚动分页控件(滑动版) - 开源研究系列文章
· 上周热点回顾(6.30-7.6)
点击右上角即可分享
微信分享提示