HDU 2588 數論 尤拉函式
阿新 • • 發佈:2018-12-31
題意很簡單,思路卻有點難想。
從已知條件一步步來分析:
因
可得出結論1,也是該題重要的突破口:
GCD(X,N)一定是N的約數
這個條件可以給我們一定啟發,因為 N 的約數一定是很有限的,我們可不可以列舉N的約數
假設我們已經得到了這樣一個
<==> 求【1,N】中有多少個數X,滿足
想到這裡,解法其實離我們已經很近了。
列舉X的複雜度是 O(N),我們還有沒有更好的解法呢?
假設當前有一個滿足條件的X,讓我們來考慮他的性質
一.因為 GCD(X,N) = P的,所以 X/P 一定與 N/P 互質(結論很顯然)
二.因為
由這兩條性質 再結合尤拉函式的定義,很顯然:
求X的個數 <==> 求 不大於N/P且與其互質的 X/P的個數 即求
聽說還有容斥的做法 但現在沒有一點思路,如果以後懂了再補上(佔坑
好像又亂立了一個flag
程式碼:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll euler(ll x){
ll res = x;
for(int i=2 ;i*i<=x ;i++){
if(x%i == 0){
res = res/i*(i-1);
while(x%i==0) x/=i;
}
}
if(x>1) res = res/x*(x-1);
return res;
}
int main(){
int T;
scanf("%d",&T);
while (T--){
ll n,m;
scanf("%I64d%I64d",&n,&m);
ll ans = 0;
for(ll i=1 ;i*i<=n ;i++){
if(n%i == 0){
if(i >= m){
ans += euler(n/i);
}
if((n/i)>=m && n/i != i){
ans += euler(i);
}
}
}
printf("%I64d\n",ans);
}
return 0;
}