1. 程式人生 > >BZOJ 2818: 尤拉篩法求gcd(x,y)==k(k為質數)

BZOJ 2818: 尤拉篩法求gcd(x,y)==k(k為質數)

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

GCD(px,py)==p;
有GCD(x,y)==1,在1-n/p的情況數。即1-n/p的尤拉和。p為質數。
所以直接模板套上篩。。就可以了。。
注意(2,4)(4,2)是兩種情況要*2.。但是(2,2)這種有不是,又要剪掉。。

#include<bits/stdc++.h>
using namespace std; #define LL long long const int mod=1000000007; const int maxn=10000005; bool check[maxn]; //用於打表記錄的中間量 LL sumPhi[maxn]; //前i個的尤拉函式和 int cnt,phi[maxn],prime[maxn]; //素數個數,尤拉表,素數表 //素數表是第幾個素數是什麼,尤拉表是i的尤拉是phi[i]; void init(int n){ //素數+尤拉表 phi[1]=1; cnt=0; for
(int i=2;i<=n;i++){ if(!check[i]){ phi[i]=i-1; prime[cnt++]=i; } for(int j=0;j<cnt;j++){ if(i*prime[j]>n)break; check[i*prime[j]]=true; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break
; } else{ phi[i*prime[j]]=phi[i]*(prime[j]-1); } } } sumPhi[0]=0; for(int i=1;i<=n;i++) sumPhi[i]=(sumPhi[i-1]+phi[i]); } int main(){ int n; while(cin>>n){ LL ans=0; init(n); for(int i=0;i<cnt;i++){ ans+=sumPhi[n/prime[i]]; } cout<<2*ans-cnt<<endl; } return 0; }

相關推薦

BZOJ 2818: gcd(x,y)==k(k質數

Description 給定整數N,求1<=x,y<=N且Gcd(x,y)為素數的 數對(x,y)有多少對. Input 一個整數N Output 如題 Sample Input 4 Sample Output 4 Hint

【演算法模板】素數

#include<iostream> using namespace std; const int MAXN=1000000+10; int n,cnt,prime[MAXN]; bool vis[MAXN]; void findprime(int n)

函式求法與素數

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

素數個數(埃氏

求1——n的素數的個數,有以下三種方法: 普通的O()演算法: #include<iostream> #include<cstdio> #include<cmath> using namespace std; bool isprim

線性

合數指自然數中除了能被1和本身整除外,還能被其他數(0除外)整除的數 時間複雜度O(n) 每個合數只會被他的最小的質因子篩去。  #include<iostream> #include<cmath> #include<cstring> usi

【模板】(線性

1 int n; 2 int p[MAX_N], cnt; 3 bool b[MAX_N]; 4 5 void Euler() 6 { 7 b[0] = b[1] = 1; 8 for(register int i = 2; i <= n; ++i) 9

[模板]線性素數()

用途 $O(n)$處理出n以內所有素數 原理 使用 合數=最大因數(除1和本身外)*最小質因數 的原理來篩,每個數只會被篩一次 對於每個數i,令它是某數的最大因數,然後從小到大地找<=i的素數j,則i*j是合數 直到找到某個j使得$i\%j==0$,因為再往後的話,j'> i的某個因子,

埃氏的區別

Eratosthenes篩法(Sieve of Eratosthenes) 由於思想非常簡單,故只給出實現。 void eratosthenes_sieve(int n) { totPrimes = 0; memset(flag, 0, size

數論 之 總結(艾托拉斯特尼+

1.篩法: 2.埃拉託斯特尼篩法(素數/質數篩選法): 2.1 步驟:      給出要篩數值的範圍n,找出以內的素數。先用2去篩,即把2留下,把2的倍數剔除掉;再用下一個素數,也就是3篩

素數個數-

模擬的時候真沒想到這是一道這麼麻煩的題。。。 先來看題: 素數個數 題目描述 求1,2,\cdots,N1,2,⋯,N 中素數的個數。 輸入輸出格式 輸入格式: 1 個整數N。 輸出格式: 1 個整數,表示素數的個數。

『素數(Prime)判定和線性(The sieve of Euler)』

  <更新提示>      <第一次更新>      <正文>      素數(Prime)及判定      定義      素數又稱質數,一個大於1的自然數,除了1和它自身外,不能整除其他自然數的數叫做質數,否則稱為合數。      1既不是素數也不是合數。  

【演算法】3.Eratosthenes篩選篩選素數

Eratosthenes篩法 1.原理 一個合數可以分成幾個素數的和,如果把素數(最初只知道2)的倍數全都去掉,剩下的就都是素數了 2.思路分析 去除0,1(既不是素數又不是合數) 找到佇列中最小的素數,刪除其倍數 3.程式碼實現(只給出了函

&& 函式

尤拉篩 對於O(nlognlogn)的埃拉特斯特尼篩法: >for(int i=2;i<n;i++) { if(!vis[i]) { prime[cnt++]=i;//儲存素數

分解質因數——vijos1156猩猩散步

vijos1156 從前有個人 他沉迷暴力分解質因數 inline void get(int x,int v) { for(int i=2;i*i<=x;i++) { while(x%i==0)

小於等於整數n的所有質數

篩法求n以下的質數最核心的是確定其倍數未消去的最大數p應該滿足的條件。要消去q的倍數,最小應該從q*q考察起(因為其他跟小的倍數已經由2p,3p。。。(p-1)*p消去了) 那麼消去q的倍數只需從q*q開始 到n結束(滿足不等式q*q <=n). 以下是測試程式碼: #

線性素數 學習報告

篩素數的方法有很多,先說一下Eratosthenes篩法,這種篩法的思想不難理解,就是對不超過n的每個正整數p,依次刪除p,2∗p,3∗p……(k−1)∗p,k∗p(k∗p<=n),最後沒被篩除的

Farey Sequence——(函式

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

BZOJ 2818 Gcdgcd(x,y)素數/函式/莫比烏斯反演

題目連結: BZOJ 2818 Gcd 題意: x∈[1,N],y∈[1,N],gcd(x,y)=素數的有序對(x,y)的對數。 分析: 對於一個素數p,如果gcd(x,y)=p,那麼相當於x

【線性質數】【最小質因數】淺析

尤拉篩 【演算法簡介】   由於每個大於等於2的合數必定存在一個最小的質因數,所以只要篩去每個質數的倍數就相當於篩去了所有合數。但尤拉篩相比埃氏篩最大的優化就在於尤拉篩保證個合數只被篩了一次,且是被其最小的質因數篩去的,所以尤拉篩的時間複雜度可以達到O(N)。   而如何保證每個合數都只被最小質因數篩去

BZOJ 4805 函式求和【杜教

求尤拉函式的字首和,項數小於2e9。 以目前的視野來看待杜教篩的話,感覺就像是將一個線性的式子,進一步優化,然後通過記憶化搜尋來實現的一個過程。 S(n)=∑i=1nϕ(i)S(n)=∑i=