zoukankan      html  css  js  c++  java
  • Codeforces 493 E.Devu and Birthday Celebration

    ## [$>Codeforces space 493 E.Devu and Birthday Celebration<$](http://codeforces.com/problemset/problem/493/E)

    题目大意 : 有 (q) 组询问,每次有 (n) 小朋友和 (m) 个苹果,求有多少种方案,使得每个小朋友都分到一个苹果,且每个小朋友分到的苹果的数目的 (gcd = 1),输出答案对 (10^9 + 7) 取模的值

    (1 leq n, m, q leq 10^5)

    解题思路 :

    (f(n)) 表示分苹果的方案满足 (n | gcd) 的方案数,(g(n)) 表示分苹果的方案满足 (gcd = n) 的方案数

    显然有 (f(n) = sum_{n|d} g(d))

    考虑到 (f(n)) 本质上是将 (frac{M}{n}) 个球,放到 (N) 个不同盒子里盒子不能为空的方案数,插板法组合数求解即可

    通过简单的莫比乌斯反演可以得到 (g(n) = sum_{n|d} mu(frac{n}{d}) f(d))

    实际上对于每一组询问我们要求的就是 (g(1)) 的值,而对于 (f(n)) 来说,只有当 (n|M) 的时候才可能有值

    所以只需要大力枚举 (M) 的因子,预处理组合数和莫比乌斯函数 (O(1)) 计算单个 (f) 的值即可

    总复杂度是 (O(Qsqrt{m}))


    /*program by mangoyang*/
    #include<bits/stdc++.h>
    #define inf (0x7f7f7f7f)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
        int f = 0, ch = 0; x = 0;
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
        for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        if(f) x = -x;
    }
    #define int ll
    
    const int N = 200005, Mod = 1000000007;
    int js[N], mu[N], b[N], prime[N], inv[N], tot, n, m;
    
    inline int Pow(int a, int b){
        int ans = 1;
        for(; b; b >>= 1, a = a * a % Mod) 
            if(b & 1) ans = ans * a % Mod; 
        return ans;
    }
    inline void Prework(){
        mu[1] = 1, js[0] = 1, inv[0] = 1;
        for(int i = 1; i < N; i++) 
            js[i] = js[i-1] * i % Mod, inv[i] = Pow(js[i], Mod - 2);
        for(int i = 2; i < N; i++){
            if(!b[i]) prime[++tot] = i, mu[i] = -1;
            for(int j = 1; j <= tot && i * prime[j] < N; j++){
                b[i*prime[j]] = 1;
                if(i % prime[j]) mu[i*prime[j]] = -mu[i]; else break; 
            } 
        }
    }
    
    inline int C(int n, int i){ return js[n] * inv[i] % Mod * inv[n-i] % Mod; }
    inline int calc(int x){ return x < m ? 0 : C(x - 1, m - 1) * mu[n/x] % Mod; }
    
    inline void solve(){
        int ans = 0; read(n), read(m);
        int num = (int) sqrt(n);
        for(int i = 1; i <= num; i++) if(n % i == 0){
            int x = i, y = n / i;
            (ans += calc(x)) %= Mod;
            if(x != y) (ans += calc(y)) %= Mod; 
        }
        printf("%lld
    ", ((ans % Mod) + Mod) % Mod);
    }
    
    signed main(){
        Prework();
        int T; read(T); while(T--) solve();
        return 0;
    }
    
  • 相关阅读:
    准确率,召回率,F值
    残差
    字典学习
    深度学习
    cnn 滤波
    tensorflow
    kaggle 泰坦尼克
    python matplotlib
    数学家西蒙斯:华尔街最赚钱的基金经理
    Oracle学习笔记:删除数据空格(trim、ltrim、rtrim函数)
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9445720.html
Copyright © 2011-2022 走看看