Codeforces 439E Devu and Birthday Celebration(计数问题)

题目链接:Codeforces 439E Devu and Birthday Celebration

题目大意:给出q,表示询问的次数,每次询问有n和f,问有多少种分类方法,将n分成f份,并且这f份的最大共约数为1.

解题思路:如果不考虑说最大共约数为1的话,那么问题很简单,就是f个数的和为n的种数C(f?1n?1).所以我们就尽量将问题转化成说f数的和为s的子问题。用容斥原理,总的可能减去公约数不为1的情况,那么公约数不为1的情况就去枚举公约数。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

const int N = 1e5+5;
const int MOD = 1e9+7;

vector<int> vec;
int fact[N], ive_fact[N];

int power (int x, int n) {
    int ans = 1;

    while (n) {
        if (n&1)
            ans = (1ll * ans * x) % MOD;

        n /= 2;
        x = (1ll * x * x) % MOD;
    }
    return ans;
}

void init () {
    fact[0] = 1;
    for (int i = 1; i < N; i++)
        fact[i] = (1ll * fact[i-1] * i) % MOD;

    for (int i = 0; i < N; i++)
        ive_fact[i] = power(fact[i], MOD-2);
}

void divFactor(int cur) {  

    vec.clear();
    int tmp = sqrt(cur+0.5);
    for (int i = 2; i <= tmp; i++) {
        if (cur % i == 0) {
            vec.push_back(i);
            while (cur % i == 0)
                cur /= i;
        }
    }  

    if (cur != 1)
        vec.push_back(cur);
} 

int solve (int n,int f) {
    if (n < f)
        return 0;
    int ans = fact[n];
    ans = 1ll * ans * ive_fact[f] % MOD;
    ans = 1ll * ans * ive_fact[n-f] % MOD;
    return ans;
}

int cal (int n) {
    return (n % MOD + MOD) % MOD;
}

int main () {
    init();
    int cas;
    scanf("%d", &cas);

    while (cas--) {
        int n, f;
        scanf("%d%d", &n, &f);
        divFactor(n);

        int ans = 0, t = 1<<vec.size();
        for (int i = 0; i < t; i++) {
            int tmp = 1, sign = 1;
            for (int j = 0; j < vec.size(); j++) {
                if (i&(1<<j)) {
                    sign *= -1;
                    tmp *= vec[j];
                }
            }

            ans = cal(ans + sign * solve(n/tmp - 1, f - 1));
        }
        printf("%d\n", ans);
    }
    return 0;
}

Codeforces 439E Devu and Birthday Celebration(计数问题)

时间: 2024-10-15 05:09:04

Codeforces 439E Devu and Birthday Celebration(计数问题)的相关文章

codeforces 439D Devu and Partitioning of the Array(有深度的模拟)

题目 //参考了网上的代码 注意答案可能超过32位 //要达成目标,就是要所有数列a的都比数列b的要小或者等于 //然后,要使最小的要和最大的一样大,就要移动(大-小)步, //要使较小的要和较大的一样大,也是要移动(较大-较小)步 //然后都加在一起就好了 #include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> using namespace std; #def

Codeforces 439C Devu and Partitioning of the Array(模拟)

题目链接:Codeforces 439C Devu and Partitioning of the Array 题目大意:给出n个数,要分成k份,每份有若干个数,但是只需要关注该份的和为奇数还是偶数,要求偶数堆的个数为p.输出方案. 解题思路:首先先将数组按照奇偶排序,也可以分开储存.然后先单独分k-p个奇数,然后后面的就将两个奇数当一个偶数分配,分配过程中计算是否满足,比如说奇数是否成对,以及是否分成了k堆. #include <cstdio> #include <cstring>

Codeforces 439D Devu and his Brother(排序)

题目链接:Codeforces 439D  Devu and his Brother 题目大意:Devu和他的哥哥互相深爱着对方,我确信他们是搞基的,为此我还去查了一下Devu是男人名还是女人名,但是后来发现His Brother,所以可以证明,他们就是搞基的.题目很简单,父亲给了他们两个人分别一个数组.但是Devu希望自己最小的数都可以不必哥哥最大的数小,现在对数组中的数有两种操作,一种是加1,一种是减1,问最少进行几次操作可以使得两个数组满足要求. 解题思路:将两个数组合并在一起,然后排序,

codeforces 451E Devu and Flowers

题意:有n个瓶子每个瓶子有 f[i] 支相同的颜色的花(不同瓶子颜色不同,相同瓶子花视为相同) 问要取出s支花有多少种不同方案. 思路: 如果每个瓶子的花有无穷多.那么这个问题可以转化为  s支花分到n个瓶子有多少种方案  用隔板法就能解决 C(s+n-1,n-1) .有限制之后我们可以 用 没限制的去减掉那些违反限制的 如果只有一个瓶子取得花超出上限 那么减去,两个瓶子 要加上(容斥原理) n只有20  就能暴力枚举那些取超过上限f[i]的瓶子并且在这些瓶子至少选出 f[i]+1 支花  统计

Codeforces 451E Devu and Flowers(容斥原理)

题目链接:Codeforces 451E Devu and Flowers 题目大意:有n个花坛.要选s支花,每一个花坛有f[i]支花.同一个花坛的花颜色同样,不同花坛的花颜色不同,问说能够有多少种组合. 解题思路:2n的状态,枚举说那些花坛的花取超过了,剩下的用C(n?1sum+n?1)隔板法计算个数.注意奇数的位置要用减的.偶数的位置用加的.容斥原理. #include <cstdio> #include <cstring> #include <cmath> #in

codeforces 439C Devu and Partitioning of the Array(烦死人的多情况的模拟)

题目 //这是一道有n多情况的烦死人的让我错了n遍的模拟题 #include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> using namespace std; int a[100010],n,k,p; int vis[100010]; int ji=0,ou=0; int main() { memset(vis,0,sizeof(vis)); cin >>

codeforces 439 E. Devu and Birthday Celebration 组合数学 容斥定理

题意: q个询问,每一个询问给出2个数sum,n 1 <= q <= 10^5, 1 <= n <= sum <= 10^5 对于每一个询问,求满足下列条件的数组的方案数 1.数组有n个元素,ai >= 1 2.sigma(ai) = sum 3.gcd(ai) = 1 solution: 这道题的做法类似bzoj2005能量采集 f(d) 表示gcd(ai) = d 的方案数 h(d) 表示d|gcd(ai)的方案数 令ai = bi * d 则有sigma(bi)

codeforces C. Devu and Partitioning of the Array

题意:给你n个数,然后分成k部分,每一个部分的和为偶数的有p个,奇数的有k-p个,如果可以划分,输出其中的一种,不可以输出NO; 思路:先输出k-p-1个奇数,再输出p-1个偶数,剩余的在进行构造.  奇数+奇数=偶数. 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <iostream> 5 #include <algorithm> 6 #defin

Codeforces 451E Devu and Flowers(组合计数)

题目地址 在WFU(不是大学简称)第二次比赛中做到了这道题.高中阶段参加过数竞的同学手算这样的题简直不能更轻松,只是套一个容斥原理公式就可以.而其实这个过程放到编程语言中来实现也没有那么的复杂,不过为了让计算机在限定的时间内完成计算需要进行一些对计算上的优化.模MOD的情况下计算组合数nCr只需要求出分子再乘以分母的逆元,考虑到模的是1e9+7本身就是一个质数,根据费马小定理a^(MOD-2)即是a在模MOD意义下的逆元.求逆元的时候为了节约计算时间可以采用快速幂.计算过程就是容斥原理,就没有什