HDU

原题链接
题意:
给你两个数 (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
",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
",sum);
    }
    return accept;
}
原文地址:https://www.cnblogs.com/Tianwell/p/11413080.html