HDU.2588 GCD (欧拉函数)
标签(空格分隔): 数论
题意分析
我怎么也看不出来这是一道欧拉函数的题目,也是参考了别人的解法写的。
题意就是计算1-N区间里有多少数和N的gcd是大于M的。
枚举所有可能情况计算肯定超时。
考虑这样一件事情,我们枚举i∈[1,N],令
N=a∗bi=a∗d
当gcd(N,i)=a,并且a≥M的时候,此时的i明显是符合要求的,但是枚举
由于
这样一来从枚举i,转换成了枚举公因子
手推算几组小数据,就不难发现,其实有重复的枚举,如对于N=10,我们可能枚举到a=2,b=5同时又枚举到了a=5,b=2。
然而这两种情况其实可以在一次枚举中全部计算出来。所以枚举范围a∈[1,sqrt(N)],当我们计算出其另一个因子,即b=N/a 也大于M的时候,就可以将
具体写法见代码。
代码总览
#include <bits/stdc++.h>
using namespace std;
int getPhi(int x){
int ret = x;
for(int i = 2; i * i <= x; ++i)
if(x % i == 0){
while(x % i== 0) x /= i;
ret -= ret / i;
}
if(x > 1) ret -= ret / x;
return ret;
}
int n,m,t;
int main()
{
scanf("%d",&t);
while(t--){
int ans =0;
scanf("%d %d",&n,&m);
for(int i = 1;i*i<=n;++i){
if(n % i == 0){
if(n/i >= m) ans+= getPhi(i);
if(i>=m && i*i !=n ) ans+=getPhi(n/i);
}
}
printf("%d\n",ans);
}
return 0;
}