容斥定理 njust1923 triple

传送门:点击打开链接

题意:给n,m,求1~n中选3个不相等的数出来,3个数的最大公约数等于m的组合数有多少。(n, m <= 1e5)

思路:我们很容易通过组合,可以求出,3个数的最大公约数是i的倍数的组合数,即C(n/i, 3)

但是,我们需要的是最大公约数是m的组合数,所以我们先通过求出m的倍数的,然后把其他倍数的个数减去就行了

所以我们倒着做就ok了,复杂度O(nlogn)

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

const int MX = 1e5 + 5;

LL F[MX];
LL f(LL n) {
    return n * (n - 1) * (n - 2) / 6;
}
int main() {
    //FIN;
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        memset(F, 0, sizeof(F));
        for(int i = m; i <= n; i += m) {
            F[i] = f(n / i);
        }
        for(int i = n; i >= m; i--) {
            if(F[i]) {
                for(int j = i * 2; j <= n; j += i) {
                    F[i] -= F[j];
                }
            }
        }
        printf("%lld\n", F[m]);
    }
    return 0;
}


你可能感兴趣的:(容斥定理 njust1923 triple)