容斥求範圍內互質的個數 (njustoj 1922 count_prime)
阿新 • • 發佈:2019-02-01
/*
題目描述: 給定你一個數n,請你統計出在[a,b]這個區間中和n互質的數的個數。
兩個數互質當且僅當他們除了1之外沒有其他的公共因子或者他們最大的公共因子是1。1和任何數是互素的。
輸入: 第一行輸入一個整數T(1 <= T <= 100),表示T組測試資料。
接下來T行,每行3個整數a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔開。
輸出: 輸出一個整數表示和n互質的數的個數。
樣例:
輸入
3 10 5
輸出
5
6
題目描述: 給定你一個數n,請你統計出在[a,b]這個區間中和n互質的數的個數。
兩個數互質當且僅當他們除了1之外沒有其他的公共因子或者他們最大的公共因子是1。1和任何數是互素的。
輸入: 第一行輸入一個整數T(1 <= T <= 100),表示T組測試資料。
接下來T行,每行3個整數a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔開。
輸出: 輸出一個整數表示和n互質的數的個數。
樣例:
輸入
2
1 10 23 10 5
輸出
5
6
*/
因為資料範圍很大不可能暴力求GCD()==1的情況所以就要用到一些技巧,,,當然算互質的個數不知這一種方法
就是在[a,b]範圍內出去n的約數及約數的倍數
#include<stdio.h> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; const int maxn=1000000; int p[maxn]; int is_p(ll n)<span style="white-space:pre"> </span>//求因子(不一定是質因子) { int tot=0; for(ll i=2;i*i<=n;i++) { if(n%i==0) { p[tot++]=i; while(n%i==0) n/=i; } } if(n>1) p[tot++]=n; return tot; } ll get(ll num,ll n) { ll ans=0; for(int i=1;i<(1<<n);i++)<span style="white-space:pre"> </span>//找出互質 { ll temp=1,flag=0; for(int j=0;j<n;j++) { if(i&(1<<j))<span style="white-space:pre"> </span>//運用二進位制的規律進行運算 { flag++; temp*=p[j]; } } if(flag&1) ans+=num/temp; else ans-=num/temp; } return ans; } int main() { int t; cin>>t; while(t--) { ll a,b,n; cin>>a>>b>>n; int tot=is_p(n); cout<<(b-get(b,tot))-(a-1-get(a-1,tot))<<endl; } return 0; }