先说一下题意,就是给你一个数n,找到1<=x<=n,且gcd(x,n)>= m
的数有多少个,暴力是肯定过不了的,这道题要用欧拉函数,在网上找了好几篇博客都没有看懂究竟怎么使用欧拉函数的,在这里说一下,便于加深一下印象。
gcd(x,n)==a,此时n=ap,x=aq,根据gcd的定义我们知道p和q肯定是互质的,
而这个时候,因为x是小于等于n的,p=n/a(a此时就是n的约数,a>=m),所以q<p.就可以转化为寻找小于p,且与p互质的个数,故欧拉函数就是用来解决这个的。此时还要注意,题目范围是1e9,如果直接从1枚举到1e9肯定会超时,所以我们枚举到sqrt(n),判断一下i和n/i的大小,就OK了。
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=205;
const int inf=0x3f3f3f3f;
int n,m,mp[maxn][maxn];
int a[maxn];
ll euler(ll n){//欧拉函数
ll ans=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
ans=ans/i*(i-1);
}
while(n%i==0)n=n/i;
}
if(n>1)ans=ans/n*(n-1);
return ans;
}
int main()
{
int t;
cin>>t;
while(t--){
ll n,m;
cin>>n>>m;
ll temp=n,ans=0;
for(int i=1;i*i<=n;i++){
if(n%i==0){
if(n/i>=m)ans+=euler(i);
if(i>=m&&n/i!=i)ans+=euler(n/i);
}
}
cout<<ans<<endl;
}
return 0;
}