nyoj 第k個互質數(二分+容斥原理)
阿新 • • 發佈:2019-01-25
第k個互質數
描述 兩個數的a,b的gcd為1,即a,b互質,現在給你一個數m,你知道與它互質的第k個數是多少嗎?與m互質的數按照升序排列。
思路: 首先要知道, 在[1,m]之間與m互質的數的個數=[1,m]之間的總個數-[1,m]之間與n不互質的數的個數 所以,要先對m進行質因數分解,求出m有哪些質因數,然後二分列舉答案mid,用容斥求[1,mid]內與m互質的數有多少個,讓其結果與k比較 判斷的時候,[1,mid]之間與m互質的數的數量 = mid - (包含一個質因子的數的個數)+(包含2個質因子的數的個數)-(包含3個質因子的數的個數)+(包含4個質因子的數的個數).....
程式碼:
描述 兩個數的a,b的gcd為1,即a,b互質,現在給你一個數m,你知道與它互質的第k個數是多少嗎?與m互質的數按照升序排列。
- 輸入
- 輸入m ,k (1<=m<=1000000;1<=k<=100000000)
- 輸出
- 輸出第k個數。
- 樣例輸入
-
10 1 10 2 10 3
- 樣例輸出
-
1 3 7
思路: 首先要知道, 在[1,m]之間與m互質的數的個數=[1,m]之間的總個數-[1,m]之間與n不互質的數的個數 所以,要先對m進行質因數分解,求出m有哪些質因數,然後二分列舉答案mid,用容斥求[1,mid]內與m互質的數有多少個,讓其結果與k比較 判斷的時候,[1,mid]之間與m互質的數的數量 = mid - (包含一個質因子的數的個數)+(包含2個質因子的數的個數)-(包含3個質因子的數的個數)+(包含4個質因子的數的個數).....
#include<stdio.h> #include<vector> using namespace std; vector<int>a;//a來儲存m的質因子 int b[100]; void div(int m) { for(int i=2;i*i<=m;i++) { if(m%i==0) a.push_back(i); while(m%i==0) m/=i; } if(m>1) a.push_back(m); } int cont(int n) { int g=0,sum=n; b[++g]=1; for(int i=0;i<a.size();i++) { int t=g; for(int j=1;j<=g;j++) { b[++t]=-1*a[i]*b[j];//偶數個質因子為正,奇數個質因子為負 sum+=n/b[t];//計算[1,n]之間有多少數含有因子b[t] } g=t; } return sum; } //二分列舉答案mid,計算[1,mid]內有多少個數與m互質,並將其結果與k比較 int Binary_search(int m,int k) { int le=1,ri=1000000000,mid; while(le<=ri) { mid=(le+ri)>>1; if(cont(mid)>=k) ri=mid-1; else le=mid+1; } return le; } int main() { int m,k; while(~scanf("%d%d",&m,&k)) { a.clear(); div(m); printf("%d\n",Binary_search(m,k)); } return 0; }