题目意思
题目中给出我们我们两个数字n,m,要求我们寻找x(x<=n) 并且gcd(x,n) >= m
题目解析
实质上我们可以寻找n的因子x,那么我们就可以确定gcd(n,x) = x
要求我们的x满足:gcd(n,x) = x >= m
设y = n/x ,那么我们就可以寻找y的质因子pi
那么pi*y一定满足下面条件:
gcd(pi*y,n) = x >= m
那么我们的问题就可以转变为求解y的所有质因子个数,即y的欧拉函数
但是这里会出现一个问题,如果我们直接遍历n,寻找n的因子的话,这样也会时间超限,然后我们会发现,如果找到了一个n的因子x,那么n/x一定也是n的因子,这样的话,我们可以直接遍历x*x <= n的情况即可
当x >= m , ans += Euler(n/x);
当n/x >= m ,ans += Euler(x); //满足另一个因子是大于m的,那么答案加Euler(n/(n/x))
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
int Euler(int n)
{
if(n == 1) return 1;
int ans = n;
for(int i = 2;i * i <= n;i ++)
{
if(n % i == 0)
{
ans -= ans/i;
while(n % i == 0) n /= i;
}
}
if(n != 1)
ans -= ans/n;
return ans;
}
int solve(int n,int m)
{
int ans = 0;
for(int i = 1;i * i <= n;i ++)
{
if(n % i ) continue;
if(i >= m && i * i != n)
ans += Euler(n/i);
if(n/i >= m)
ans += Euler(i);
}
return ans;
}
int main()
{
int T;
int n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
printf("%d\n",solve(n,m));
}
return 0;
}