求组合数的方法

1.暴力

根据阶乘公式展开,时间复杂度较高,且容易炸掉long long

2.借用double暴力来求

http://icpc.upc.edu.cn/problem.php?cid=1438&pid=9

题目描述

Imagine you are attending your math lesson at school. Once again, you are bored because your teacher tells things that you already mastered years ago (this time he’s explaining that (a+b)2=a2+2ab+b2). So you decide to waste your time with drawing modern art instead.

Fortunately you have a piece of squared paper and you choose a rectangle of size n*m on the paper. Let’s call this rectangle together with the lines it contains a grid. Starting at the lower left corner of the grid, you move your pencil to the upper right corner, taking care that it stays on the lines and moves only to the right or up. The result is shown on the left:
在这里插入图片描述

Really a masterpiece, isn’t it? Repeating the procedure one more time, you arrive with the picture shown on the right. Now you wonder: how many different works of art can you produce?

输入

The input contains several testcases. Each is specified by two unsigned 32-bit integers n and m, denoting the size of the rectangle. As you can observe, the number of lines of the corresponding grid is one more in each dimension. Input is terminated by n=m=0.

输出

For each test case output on a line the number of different art works that can be generated using the procedure described above. That is, how many paths are there on a grid where each step of the path consists of moving one unit to the right or one unit up? You may safely assume that this number fits into a 32-bit unsigned integer.

样例输入
5 4
1 1
0 0
样例输出
126
2

输入a和b,求C(b,a+b)

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    register ll n,k,a,b;
    register ll sum,p;
    register long double sum1=1.0;
    while(scanf("%lld%lld",&n,&k)&&(n!=0||k!=0))
    {
        sum1=1.0;
        a=n+k;
        b=n<k?n:k;
        for(int i=1;i<=b;i++)
        {
            sum1=sum1*a*1.0/i;
            a--;
        }
        sum1+=0.5;
        sum=sum1;
        printf("%lld\n",sum);
    }
    return 0;
}
3.逆元求组合数

http://icpc.upc.edu.cn/problem.php?id=12104

题目描述

You are given positive integers N and M.
How many sequences a of length N consisting of positive integers satisfy a1×a2×…×aN=M? Find the count modulo 109+7.
Here, two sequences a’ and a" are considered different when there exists some i such that a’i≠a"i.

Constraints
·All values in input are integers.
·1≤N≤105
·1≤M≤109

输入

Input is given from Standard Input in the following format:
N M

输出

Print the number of the sequences consisting of positive integers that satisfy the condition, modulo 109+7.

样例输入

2 6

样例输出

4

提示

Four sequences satisfy the condition: {a1,a2}={1,6},{2,3},{3,2} and {6,1}.

思路

质因数分解,然后每个素数因子个数,设为x,转化为把x个相同的放进n个位置,开始写的n^x,但是wa,后来写的隔板法。
C(n+x-1,n-1)。
为啥不是n^x,因为元素相同,不同方案取决于每个盒子多少个球。又隔板法不能有空元素,但题目可以。所以我们添加三块隔板,答案为上。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll N=1e9+7;
ll w[505500]={0};
ll p(ll x,ll y)
{
    ll sum1=1;
    while(y)
    {
        if (y&1)
            sum1=(sum1%N*x%N)%N;
        y>>=1;
        x=(x%N*x%N)%N;
    }
    return sum1%N;
}
ll c1(ll x,ll y)
{
    if(x<y)
        swap(x,y);
    return (w[x]%N*p((w[x-y]%N*w[y]%N)%N,N-2)%N)%N;
}
int main()
{
    ll n,m;
    w[1]=1;
    for(ll i=2;i<=500500;i++)
        w[i]=(w[i-1]*i)%N;
    cin>>n>>m;
    if(n==1)
    {
        cout<<1<<endl;
        return 0;
    }
    ll sum=1;
    for(ll i=2;i*i<=m+100;i++)
    {
        if(m%i!=0)
            continue;
        ll js=0;
        while(m%i==0)
        {
            m=m/i;
            js++;
        }
        sum=(sum%N*c1(n-1,n+js-1)%N)%N;
    }
    if(m!=1)
        sum=(sum%N*n%N)%N;
    cout<<sum%N<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中,有多种方法可以组合数。下面我将介绍几种常见的方法: 1.编写函数计算组合数:可以根据给定的公式编写一个函数来计算组合数。例如,可以使用一个循环计算组合数的值。具体的代码如下: ```python def Combinatorial(n, i): # n>=i Min = min(i, n - i) result = 1 for j in range(0, Min): result = result * (n - j) / (Min - j) return result if __name__ == '__main__': print(int(Combinatorial(45, 2))) ``` 2.使用第三方模块scipy计算排列组合的具体数值:可以使用scipy库中的comb函数来计算组合数。具体的代码如下: ```python from scipy.special import comb C = comb(45, 2) print(C) ``` 3.使用阶乘的方式组合数:可以利用阶乘函数来计算组合数。具体的代码如下: ```python import math def factorial_me(n): result = 1 for i in range(2, n + 1): result = result * i return result def comb_1(n, m): return math.factorial(n) // (math.factorial(n - m) * math.factorial(m)) def comb_2(n, m): return factorial_me(n) // (factorial_me(n - m) * factorial_me(m)) if __name__ == '__main__': print(comb_1(45, 2)) print(comb_2(45, 2)) ``` 4.使用itertools列出排列组合的全部情况:可以使用itertools库中的combinations和permutations函数来列出所有的组合情况。具体的代码如下: ```python from itertools import combinations, permutations # 列举排列结果 print(list(permutations([1, 2, 3], 2))) # 列举组合结果 print(list(combinations([1, 2, 3], 2))) ``` 综上所述,以上是几种常见的Python组合数方法。你可以根据需选择合适的方法来使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [python计算排列组合数](https://blog.csdn.net/hitzijiyingcai/article/details/107021744)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Python快速组合数C(n,m)三种方法整理](https://blog.csdn.net/bianxia123456/article/details/105151104)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值