1. 程式人生 > >BZOJ-2705: [SDOI2012]Longge的問題 (歐拉函數)

BZOJ-2705: [SDOI2012]Longge的問題 (歐拉函數)

soft input while arc 打開 bbs amp %20 set

2705: [SDOI2012]Longge的問題

Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 3313 Solved: 2072
[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

round1 day1

這題是孬孬昨天跟我裝逼時考我的一道題,當時隨便口胡了一下,然後孬孬說要用莫比烏斯反演???【黑人問號.jpg】 今天偶遇了原題,迫不及待的打開題解,想看看莫比烏斯反演是什麽玩意,結果點開一看……mdzz這不就是我昨天口胡的那個方法嘛…… 然後突然驚悚,貌似今天再想一次的話不一定還能想到正解?(laj還需多加訓練!) 我們逆著想一下,求∑gcd(i, N)(1<=i <=N),思考一個數xi可能為哪些數與n的gcd? 不難想到因為是gcd所以這些數/xi後與n/xi是互質的,這就轉化為n/xi範圍內有多少個數與n/xi互質的問題,這是歐拉函數,∴就相當於求∑xi*phi(n/xi) 不能把phi表全打出來,對於每個n/xi 單獨求一遍phi即可qwq
 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 LL n,ans;
 5 LL eular(LL x){
 6     LL i,an=x;
 7     for (i=2;i*i<=x;i++)
 8         if (x%i==0){
 9             an=an/i*(i-1);
10             while (x%i==0) x/=i;
11         }
12     if (x!=1) an=an/x*(x-1);
13     return
an; 14 } 15 int main(){ 16 freopen ("question.in","r",stdin);freopen ("question.out","w",stdout); 17 int i,j; 18 scanf("%lld",&n); 19 for (i=1;i*i<n;i++) 20 if (n%i==0) 21 ans+=i*eular(n/i)+n/i*eular(i); 22 if (i*i==n) ans+=i*eular(i); 23 printf("%lld",ans); 24 return 0; 25 }

BZOJ-2705: [SDOI2012]Longge的問題 (歐拉函數)