原题链接
题意:
给你两个数 \(N,M\) 你要求出 符合条件 \(GCD(X,N)>=M,\space (1<=X<=M)\) 中\(X\)的个数
思路:
一开始没有往欧拉函数去想。总想着去筛出所有合适的因子然后统计个数,或者直接暴力for去枚举因子(肯定会TLE)
后面想到了一个互质关系(即是已知 \(GCD(X,N) = q\) \(X = q*a\) ,\(N=q*b\) \(则a,b必然互质\),然后我们就可以找到一个大于M的因子,开心的去找所有满足 小于 b 的互质个数即可。
然鹅...这不就是欧拉函数吗?所以最后我们在 用一个欧拉函数即可(离线打表和直接算都可以)
code:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <cmath> #define IOS ios::sync_with_stdio(0); cin.tie(0); #define accept 0 #define mp make_pair using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int inf = 0x3f3f3f3f; const int maxn = 1e3+7; const int maxm = 1e6+7; const int mod = 1e9+7; int euler(int n){ int i; int res = n,a = n; for(i = 2;i*i <= a; ++i){ if(a%i == 0){ res -= res/i; //p(n) = (p - p/p1)(1 - 1/p2) while(a%i == 0) a/=i; } } if(a > 1) res -= res/a;//存在大于sqrt(a)的质因子 return res; } int main() { int n, x, y, id; int t; scanf("%d",&t); while(t--){ scanf("%d%d",&x,&y); if(y==1) { printf("%d\n",x); continue; } ll sum = 0; //单个因子大小不会超过平方根 for(int i = 1; i * i <= x; ++i) { if(x % i == 0){ if(i >= y) sum += euler(x / i); if( (x / i) != i && (x / i) >= y) sum += euler(i); } } printf("%lld\n",sum); } return accept; }
来源:博客园
作者:Tianwell
链接:https://www.cnblogs.com/Tianwell/p/11413080.html