1. 程式人生 > >求數論求約數和 與 互質和演算法 (分解質因數與尤拉函式)

求數論求約數和 與 互質和演算法 (分解質因數與尤拉函式)

Description

One day, Qz met an easy problem. But after a 5-hout-long contest in CSU, he became very tired and he wanted to call his girlfriend as soon as possible. As we all know, Qz is a genius in plenty of fields especially in programming. But he did not want to write a program to solve this problem, he just want to call his girlfriend. Now he gave this problem to you, and he want you to solve this problem without programming. Fortunately, YH heard about Qz’s bad behavior, and he thought that not everyone is as clever as Qz. Finally, YH managed to persuade Qz to ask you to write a program to solve this problem. The problem is:
Qz will give you only one number N (1<= N <= 10^9), and he wants to know the answer of A sub B, A and B are as follow: A is sum of series of numbers X (He only cares about X which is no larger than N) .For each X, that exists an integer k satisfies that k * X = N. B is sum of series of numbers Y (He only cares about Y which is no larger than N).For each Y satisfies that GCD(Y, N) = 1.
YH whispers to you that GCD(X, Y) means the Greatest Common Divisor of X and Y, and you should not let Qz know that YH has told you the secret. Qz is so hurry so he had no time to give you the N one by one and he will give you multiple cases. YH is so kind and he ask Qz that for each input file, the number of N is about 30000
.

Input

Qz is so hurry to call his girlfriend so he has no time to explain the Input.

Output

Help Qz to output the answer to problems on each line.

Sample Input

1
2
3
4

Sample Output

0
2
1
3

題意:給出一個數n , 求n的約數和減去不大於n且與n互質的數的和,記為a-b。

當時去現場做想到的只有暴力,但10^9超時無疑。後來聽出題人的講解,說用到尤拉函式,當時也不怎麼明白。直到今天看到一個性質:上述的b有一個公式,b=(n*f(n))/2。

f(n)代表n的尤拉函式。(有關證明在數論書中可以找到)。

問題轉化為求n的約數和,n的尤拉函式。都需要用到分解質因數,將n分解為n=p1^a1*p2^a2*...*pn^an。n的約數和記為S(n),S(n)的公式不再贅述。

大致思路已經有了,先構造根號n的素數表,因為質因數不會超過根號n,然後就是分解質因數的過程。

該題目可以作為求約束和與不大於n且與n互質的和的模板。

#include<stdio.h>
#include<math.h>
typedef unsigned long long LL;
#define maxn 200000
LL primet[maxn];
int pnum = 0;
LL n,a,b,res;
bool flag[maxn];
void getprimtable()//篩法求出素數
{
    for (long i = 2; i < maxn; i++)
        if (!flag[i]) {
            primet[pnum++] = i;
            for (long j = i + i; j < maxn; j += i) flag[j] = true;
        }
}
LL FF(LL x ,LL y) {
    LL ret=1;
    while(y--) ret*=x;
    return ret;
}
LL eularpk(LL p, int k)//尤拉求p^k
{
    if (k == 0) return 1;
    LL ans = p - 1;
    while (--k) ans *= p;
    return ans;
}
LL f(LL n)//求f 因式分解
{
    LL sum = 1;
    res=1;
    int p, k;
    for (int i = 0; primet[i]*primet[i]<= n; i++) {
        p = primet[i];
        if (n % p == 0) {
            k = 0;
            while (n % p == 0) {n /= p; k++;}
            sum = sum * eularpk(p, k);  // p^k
            res*=( ( FF(p,k+1) -1 ) / (p-1));
        }
    }
    if (n > 1) {      // 分解到最後剩下一個素因子 , 須特別注意。
        sum = sum * eularpk(n, 1); 
        res*=( ( FF(n,2) -1 ) / (n-1));
    }
    return sum;
}
int main() {
    getprimtable();
    while(~scanf("%lld",&n)) {
        LL b=n*f(n)/2;
        if(n == 1) printf("0\n");
        else printf("%lld\n",res-b);
    }
    return 0;
}




相關推薦

數論約數 演算法 分解質因數函式

Description One day, Qz met an easy problem. But after a 5-hout-long contest in CSU, he became very tired and he wanted to call his girl

N10^14以內N的數的(容斥原理,或者函式

#include <iostream> #include <cstring> #include <algorithm> #include <cmath>

51nod 1040 1-n這n個數,同n的最大公約數函式

題目:給出一個n,求1-n這n個數,同n的最大公約數的和。比如:n = 6           1,2,3,4,5,6 同6的最大公約數分別為1,2,3,2,1,6,加在一起 = 15 思路:一個數與n的最大公約數肯定是n的因子中的一個,所以只需要列舉n的每一個因子x,然

Farey Sequence——篩法函式

傳送門 A - Farey Sequence Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d &

The Euler functionhdoj2824快速函式

The Euler function Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4757    Acce

51nod-1040 最大公約數之和函式

基準時間限制:1 秒 空間限制:131072 KB 分值: 80 難度:5級演算法題  收藏  關注 給出一個n,求1-n這n個數,同n的最大公約數的和。比如:n = 6 1,2,3,4,5,6 同6的最大公約數分別為1,2,3,2,1,6,加在一起 = 15

51nod 1040 最大公約數之和函式

水平較水,想不到,看的討論版 與n的公約數,肯定是n的因子 那我們列舉n的因子就好了 假設因子為x,那麼x的貢獻次數就是1-n有多少個數與n的gcd=x,即1-n/x有多少個數與n/x互質,即ph

【51NOD】 1040-最大公約數之和函式

原題連線 首先補充一個知識點,尤拉函式: 在數論,對正整數n,尤拉函式是小於n的正整數中與n互質的數的數目(φ(1)=1)。此函式以其首名研究者尤拉命名(Euler’s totient function),它又稱為Euler’s totient f

最大公約數之和 V2函式

【題目描述】 給出一個數N,輸出小於等於N的所有數,兩兩之間的最大公約數之和。相當於求 Ans=∑i=1i<n∑j=i+1j<ngcd(i,j)Ans=∑i=1i<n∑j=i+1j<ngcd(i,j) Input 第1行:1個數

UVA 12493 Stars (函式--1~nn的個數

大致題意:圓上有偶數n個點,每m個點連起來,最後可以把所有點串聯起來就合法。問有多少個m可以完成串聯,串聯後形狀相同的算重複 n <2^31 思路:可以寫個暴力程式,可以發現只要m與n互質,就可以完成串聯,所以用尤拉函式解決 證明: 設cnt為當第一次達到原點時

1~n中m的數的個數m>n 附hdu1695題解(函式+容斥原理)

int calc(int n,int m) { //求1~n 與m互質的數的個數 int num=getFactors(m); //先將m分解質因數 int sum=0; //先求出不互質的個數,最後用n減去該數 for(int state=1;

函式n的數的個數

求解與n(1-n-1)互質的質因子的個數 解析:(轉) 定義:對於正整數n,φ(n)是小於或等於n的正整數中,與n互質的數的數目。     例如:φ(8)=4,因為1,3,5,7均和8互質。 性質:1.若p是質數,φ(p)= p-1. 2.若n是質數p的k

容斥範圍內的個數 njustoj 1922 count_prime

/* 題目描述: 給定你一個數n,請你統計出在[a,b]這個區間中和n互質的數的個數。兩個數互質當且僅當他們除了1之外沒有其他的公共因子或者他們最大的公共因子是1。1和任何數是互素的。 輸入: 第一行輸入一個整數T(1 <= T <= 100),表示T組測試資料

函式

尤拉函式 :尤拉函式是數論中很重要的一個函式,尤拉函式是指:對於一個正整數 n ,小於 n 且和 n 互質的正整數(包括 1)的個數,記作 φ(n) 。 完全餘數集合:定義小於 n 且和 n 互質的數構成的集合為 Zn ,稱呼這個集合為 n 的完全餘數集合。 顯然 |Zn|

數論】線性篩素數,線性篩函式前N個數的約數個數

先來最基本的線性篩素數,以後的演算法其實都是基於這個最基本的演算法: #include<stdio.h> #include<string.h> #define M 10000000 int prime[M/3]; bool flag[M]; void

一個數的因子以及函式

求一個數的質因子 程式碼:#include<stdio.h> int main() { long long a[100],num,i,n; while(~scanf("%I64d",&n)) { num=0;

函式提供1到N中N的數

當個板子放著,具體是看了這篇部落格:尤拉函式求法與應用 尤拉函式用希臘字母φ表示,φ(N)表示N的尤拉函式. 對φ(N)的值,我們可以通俗地理解為小於N且與N互質的數的個數(包含1). //直接求解尤拉函式 int euler(int n){ //返回euler(n

函式求法篩法素數

尤拉函式:     尤拉函式定義:        對於正整數n,尤拉函式Euler(n)是1到n-1中與n互質的數的個數,特別的,Euler(1) = 1,若n為質數則有 Euler(n) = n - 1      尤拉函式的兩種求法:     1.由定義和常識可以知道對

函式小於或等於n的數中n的數的數目

【尤拉函式】 在數論,對正整數n,尤拉函式是少於或等於n的數中與n互質的數的數目。此函式以其首名研究者尤拉命名,它又稱為Euler's totient function、φ函式、尤拉商數等

一類函式相關的和式推導

\(\\\) 寫在前面 因為最近做了不少和尤拉函式相關的求和問題,而這一類求和的推導有沒有涉及到反演和卷積,所以單獨寫一寫。 給出的題目順序與難度大致無關,是按照個人做題的順序安排的。 再次宣告尤拉函式的定義:\(\varphi(x)\) 表示 \([1,x]\) 裡的所有整數中,與 \(x\)