题意:求解小于n的数i且gcd(i,n)大于m的i的个数
分析:
对于所有小于n的最大公约数值一定是n的因子,所以,从这个方面下手找i为n的因子且i>m时求解车i的素数倍数且小于n的个数累加起来就好了。以为这个倍数最大为n/i所以求得n/i的欧拉函数值累加起来就好了。
代码如下:
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <utility>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
long long euler(long long n){ //返回euler(n)
long long res=n,a=n;
for(long long i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
//欧拉函数值
long long a[1000010];
int main(){
long long n,m;
int t;
cin>>t;
while(t--){
long long ans=0;
scanf("%I64d%I64d",&n,&m);
for(int i=1;i*i<=n;i++){//判断sqrt(n)就好
if(n%i!=0)continue;
if(i>=m&&i*i!=n){
ans+=euler(n/i);
}
if(n/i>=m){
ans+=euler(i);//一个是i,一个是n/i
}
}
printf("%I64d\n",ans);
}
return 0;
}