XDU 1149 卡尔的技能 II (容斥 多重集组合 阶乘逆元)

2024-03-20 13:32

本文主要是介绍XDU 1149 卡尔的技能 II (容斥 多重集组合 阶乘逆元),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1149: 卡尔的技能 II

时间限制: 2 Sec   内存限制: 128 MB


题目链接:http://acm.xidian.edu.cn/problem.php?id=1149

题目分析:首先这是一个多重集组合问题,请见多重集组合,所有不超过k,那就是个典型的容斥问题了,先求出总的情况数C(n + m - 1, m),然后用总的减去有至少1种元素超过k次加上至少有2种元素超过k次。。。有i种元素超过k次方案数是两部分的积
1. C(n, i)表示从n种里选出i种
2. C(n + m - i * (k + 1) - 1, m - i * (k + 1)),这是多重集组合公式,表示种类数为n,次数为m - i * (k + 1)的多重集组合,因为至少有i个超过k次,那么每个最少要分配k + 1,所以剩下的次数就是m - i * (k + 1)
求组合数的时候直接预处理阶乘和阶乘逆元,则可以在线O(1)求得,最后注意答案可能为负,因此要加个MOD

#include <cstdio>  
#define ll long long  
int const MOD = 1e9 + 7;  
int const MAX = 2e6 + 5;  
ll n, m, k;
ll fac[MAX + 5], inv_fac[MAX + 5];ll qpow(ll x, ll n)  
{  ll res = 1;  while(n)  {  if(n & 1)  res = (res * x) % MOD;  x = (x * x) % MOD;  n >>= 1;  }  return res;  
}  void Init_fac()
{fac[0] = 1;for(int i = 1; i <= MAX; i++)fac[i] = (fac[i - 1] * i) % MOD;inv_fac[MAX] = qpow(fac[MAX], MOD - 2);for(int i = MAX - 1; i >= 0; i--)inv_fac[i] = (inv_fac[i + 1] * (i + 1) % MOD) % MOD;
}ll C(ll n, ll i)
{if(i > n)return 0;return ((((fac[n] % MOD) * (inv_fac[i] % MOD)) % MOD) * (inv_fac[n - i] % MOD)) % MOD;
}int main()  
{   Init_fac();while(scanf("%lld %lld %lld", &n, &m, &k) != EOF){  if(n * k < m){printf("0\n");continue;}if(k > m)k = m;ll ans = C(n + m - 1, m), sign = -1;for(ll i = 1; i <= n; i++, sign = -sign)  {ll tmp = m - i * (k + 1);if(tmp < 0)break;ans = ((ans % MOD) + (sign * C(n, i) * C(n + tmp - 1, tmp)) % MOD) % MOD;}printf("%lld\n", (ans + MOD) % MOD);}  
} 


这篇关于XDU 1149 卡尔的技能 II (容斥 多重集组合 阶乘逆元)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829597

相关文章

hdu4828(卡特兰数+逆元)

这题的前几个数据分别为1,2,5,14,32......................然后确定这是个卡特兰数列 下面来介绍下卡特兰数,它的递推式为f[i+1] = f[i]*(4*n - 6)/n,其中f[2] = f[3] =1;f[4] = 2;f[5] = 14;f[6] = 32.................................. 但是这题的n太大了,所以要用到逆元,

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

uva 10061 How many zero's and how many digits ?(不同进制阶乘末尾几个0)+poj 1401

题意是求在base进制下的 n!的结果有几位数,末尾有几个0。 想起刚开始的时候做的一道10进制下的n阶乘末尾有几个零,以及之前有做过的一道n阶乘的位数。 当时都是在10进制下的。 10进制下的做法是: 1. n阶位数:直接 lg(n!)就是得数的位数。 2. n阶末尾0的个数:由于2 * 5 将会在得数中以0的形式存在,所以计算2或者计算5,由于因子中出现5必然出现2,所以直接一

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu

hdu4059容斥原理

求1-n中与n互质的数的4次方之和 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWrit

从0到1,AI我来了- (7)AI应用-ComfyUI-II(进阶)

上篇comfyUI 入门 ,了解了TA是个啥,这篇,我们通过ComfyUI 及其相关Lora 模型,生成一些更惊艳的图片。这篇主要了解这些内容:         1、哪里获取模型?         2、实践如何画一个美女?         3、附录:               1)相关SD(稳定扩散模型的组成部分)               2)模型放置目录(重要)

ural 1149. Sinus Dances dfs

1149. Sinus Dances Time limit: 1.0 second Memory limit: 64 MB Let  An = sin(1–sin(2+sin(3–sin(4+…sin( n))…) Let  Sn = (…( A 1+ n) A 2+ n–1) A 3+…+2) An+1 For given  N print  SN Input One

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图