组合计数我最爱

  • Max-Min Sums
    • description
    • solution
    • code
  • Binomial Coefficient is Fun
    • description
    • solution
    • code
  • Strivore
    • description
    • solution
    • code
  • Bubble Sort
    • description
    • solution
    • code
  • [HAOI2016]放棋子
    • description
    • solution
    • code
  • EntropyIncreaser 与 Minecraft
    • description
    • solution
    • code
  • D - Iroha and a Grid
    • description
    • solution
    • code

Max-Min Sums

description

solution

加法对于max⁡/min⁡\max/\minmax/min有分配率,所以单独考虑每个iii做最大值/最小值的贡献,加起来即可

把aaa排序后,前面选k−1k-1k−1个自己做最大值,后面选k−1k-1k−1个自己做最小值

code

#include <cstdio>
#include <algorithm>
using namespace std;
#define mod 1000000007
#define int long long
#define maxn 100005
int n, k;
int A[maxn], sum[maxn], fac[maxn], inv[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}int C( int n, int m ) {if( n < m ) return 0;return fac[n] * inv[m] % mod * inv[n - m] % mod;
}signed main() {scanf( "%lld %lld", &n, &k );inv[0] = fac[0] = 1;for( int i = 1;i <= n;i ++ )fac[i] = fac[i - 1] * i % mod;inv[n] = qkpow( fac[n], mod - 2 );for( int i = n - 1;i;i -- )inv[i] = inv[i + 1] * ( i + 1 ) % mod;for( int i = 1;i <= n;i ++ )scanf( "%lld", &A[i] );sort( A + 1, A + n + 1 );int ans = 0;for( int i = 1;i <= n;i ++ )ans = ( ans + C( i - 1, k - 1 ) * A[i] - C( n - i, k - 1 ) * A[i] ) % mod;printf( "%lld\n", ( ans + mod ) % mod );return 0;
}

Binomial Coefficient is Fun

description

solution

要乘积产生贡献,必须满足Bi≥AiB_i\ge A_iBi​≥Ai​,∑iBi≤m\sum_{i}B_i\le m∑i​Bi​≤m,看成mmm个空位

把至少要求的AiA_iAi​看成第iii根小棒,不同iii之间加一条分割线分开,AnA_nAn​的分割线则划分了∑iBi\sum_iB_i∑i​Bi​的范围

总共是n+mn+mn+m个空位(新增了nnn条分割线空位),从中放∑iAi+n\sum_iA_i+n∑i​Ai​+n根小棒和分割线

小棒和分割线是没有区别的,用组合数求

前A1A_1A1​根小棒划分范围表示B1B_1B1​,以第A1+1A_1+1A1​+1根小棒(分割线)划分不同的BBB

第A1+2A_1+2A1​+2到A1+B1+1A_1+B_1+1A1​+B1​+1根小棒划分范围表示B2B_2B2​,以此类推

就与问题的所求式子方案对应

code

#include <cstdio>
#define int long long
#define mod 1000000007
int n, m, sum;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}signed main() {scanf( "%lld %lld", &n, &m );for( int i = 1, x;i <= n;i ++ )scanf( "%lld", &x ), sum += x;int ans = 1;for( int i = m - sum + 1;i <= n + m;i ++ )ans = ans * i % mod;for( int i = 1;i <= sum + n;i ++ )ans = ans * qkpow( i, mod - 2 ) % mod;printf( "%lld\n", ans );return 0;
}

Strivore

description

solution

转化为求n+∣s∣n+|s|n+∣s∣的字符串,使得sss是其一个(可以不相邻的)子序列

非常恶心的就是如果插入的字符与相邻字符相同,那么插左边插右边本质是没有区别的

只有个数的改变,但是如果单纯用组合数来算,显然会算成多种方案

e.g. 要插ooo中,插左/插右/插中间,最后结果都是ooo,理应算成一种

所以强制的分类,左右边,在右边的数就可以随便选,在左边的数,就强制与即将相邻字符不同

枚举字符串sss最后一位的位置(相当于枚举在右边的数的个数)

在其右边的随便选,左边的去除掉禁止的字符

∑i=0n26i×25n−iCn−i+∣s∣−1n−i\sum_{i=0}^n26^i\times 25^{n-i}C_{n-i+|s|-1}^{n-i}i=0∑n​26i×25n−iCn−i+∣s∣−1n−i​

∣s∣−1|s|-1∣s∣−1就是减去字符串最后一位位置,因为右边个数确定,伴随着最后一个位置确定

有n−in-in−i个位置还可以随便选,剩下的位置就必须按照sss的长相依次填充

code

#include <cstdio>
#include <cstring>
#define maxn 2000005
#define int long long
#define mod 1000000007
int fac[maxn], inv[maxn];
char s[maxn];
int n, m;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void init( int n ) {fac[0] = inv[0] = 1;for( int i = 1;i <= n;i ++ )fac[i] = fac[i - 1] * i % mod;inv[n] = qkpow( fac[n], mod - 2 );for( int i = n - 1;i;i -- )inv[i] = inv[i + 1] * ( i + 1 ) % mod;
}int C( int n, int m ) {return fac[n] * inv[m] % mod * inv[n - m] % mod;
}signed main() {scanf( "%lld %s", &n, s + 1 );m = strlen( s + 1 );init( n + m );int ans = 0;for( int i = 0;i <= n;i ++ )ans = ( ans + qkpow( 26, i ) * qkpow( 25, n - i ) % mod * C( n - i + m - 1, n - i ) % mod ) % mod;printf( "%lld\n", ans );return 0;
}

Bubble Sort

description

solution

定义函数f(x):xf(x):xf(x):x元素左边且比xxx大的元素个数

  • ∀xf(x)=0\forall_xf(x)=0∀x​f(x)=0表示有序状态
  • f(x)≤n−xf(x)\le n-xf(x)≤n−x
  • 每一轮的冒泡排序,若f(x)≠0f(x)≠0f(x)​=0,则f(x)−−f(x)--f(x)−−

显然max⁡{f(x)}=k\max\{f(x)\}=kmax{f(x)}=k才恰好是kkk轮的冒泡排序

比起求恰好kkk轮的冒泡排序,不超过kkk轮的冒泡排序g(k)g(k)g(k)更好求

∀xn−x≤k⇒n−k≤x\forall_xn-x\le k\Rightarrow n-k\le x∀x​n−x≤k⇒n−k≤x,满足此条件的xxx可以随便放

在nnn个位置中放置n−kn-kn−k个数后,剩下数的放置方案数k!k!k!

对于前n−kn-kn−k个放置的数

f(1)≤k⇒1f(1)\le k\Rightarrow 1f(1)≤k⇒1有k+1k+1k+1个位置可以放(前k+1k+1k+1个),111对f(2)f(2)f(2)不会有影响,所以222同样有k+1k+1k+1个位置可放.........

最终结果为g(k)−g(k−1)=k!((k+1)n−k−kn−k)g(k)-g(k-1)=k!\Big((k+1)^{n-k}-k^{n-k}\Big)g(k)−g(k−1)=k!((k+1)n−k−kn−k)

code

#include <cstdio>
#define int long long
#define mod 20100713
#define maxn 1000005
int fac[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
} signed main() {int T, n, k;scanf( "%lld", &T );fac[0] = 1;for( int i = 1;i <= 1e6;i ++ )fac[i] = fac[i - 1] * i % mod;while( T -- ) {scanf( "%lld %lld", &n, &k );printf( "%lld\n", ( qkpow( k + 1, n - k ) - qkpow( k, n - k ) + mod ) % mod * fac[k] % mod );}return 0;
}

[HAOI2016]放棋子

description

solution

每行每列都只有一个障碍,除去这些障碍,保证每行每列恰好只放了一个棋子的方案数

本质其实就是错排数,障碍就相当于iii自身(在方案中不能与iii下标对应)

知道这个后就剩下大整数操作了

没有模数真是难,有了模数还是难

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct Int {int g[5000], len;Int() {memset( g, 0, sizeof( g ) );len = 0;}Int( int x ) {memset( g, 0, sizeof( g ) );len = 0;if( ! x ) len = 1;else while( x )g[len ++] = x % 10, x /= 10;}void clean() {while( len > 1 && ! g[len - 1] ) len --;}Int operator + ( Int t ) {static Int ans;ans.len = 0; int r = 0;for( int i = 0;i < max( len, t.len );i ++ ) {int x = r;if( i < len ) x += g[i];if( i < t.len ) x += t.g[i];ans.g[ans.len ++] = x % 10;r = x / 10;}ans.g[ans.len ++] = r;ans.clean();return ans;}Int operator * ( Int t ) {Int ans;ans.len = t.len + len;for( int i = 0;i < len;i ++ )for( int j = 0;j < t.len;j ++ )ans.g[i + j] += g[i] * t.g[j];for( int i = 0;i < ans.len;i ++ )ans.g[i + 1] += ans.g[i] / 10, ans.g[i] %= 10;ans.len ++;ans.clean();return ans;}void print() {for( int i = len - 1;~ i;i -- )printf( "%d", g[i] );}
}D[205];
int main() {int n;scanf( "%d", &n );D[1] = 0, D[2] = 1;for( int i = 3;i <= n;i ++ )D[i] = ( D[i - 1] + D[i - 2] ) * ( i - 1 );D[n].print();return 0;
}

EntropyIncreaser 与 Minecraft

description

solution

∑i=1nxi≤p\sum_{i=1}^nx_i\le p∑i=1n​xi​≤p的形式很难不联想到Binomial Coefficient is Fun一题的形式

枚举有多少个xi=0x_i=0xi​=0,剩下kkk个∣xi∣>0|x_i|>0∣xi​∣>0,那么方案数首先有2k2^k2k

设∀i,xi≥0yi=xi+1⇒∑i=1kyi≤p⇒∑i=1kxi≤p−k\forall_{i,x_i\ge 0}\ y_i=x_i+1\Rightarrow \sum_{i=1}^ky_i\le p\Rightarrow \sum_{i=1}^kx_i\le p-k∀i,xi​≥0​ yi​=xi​+1⇒∑i=1k​yi​≤p⇒∑i=1k​xi​≤p−k

对于∑i=1kxi=p\sum_{i=1}^kx_i=p∑i=1k​xi​=p的方案数利用n−1n-1n−1个档板的挡板法求解Cp+n−1n−1C_{p+n-1}^{n-1}Cp+n−1n−1​

枚举ppp,答案为∑k=0nCnk2k∑i=0pCi−k+k−1k−1⇔∑k=0nCnk2k∑i=0p−1Cik−1\sum_{k=0}^nC_n^k2^k\sum_{i=0}^pC_{i-k+k-1}^{k-1}\Leftrightarrow \sum_{k=0}^nC_n^k2^k\sum_{i=0}^{p-1}C_{i}^{k-1}∑k=0n​Cnk​2k∑i=0p​Ci−k+k−1k−1​⇔∑k=0n​Cnk​2k∑i=0p−1​Cik−1​

∑i=0nCim=Cn+1m+1⇒ans=∑k=0nCnk2kCpk\sum_{i=0}^nC_i^m=C_{n+1}^{m+1}\Rightarrow ans=\sum_{k=0}^nC_n^k2^kC_{p}^{k}∑i=0n​Cim​=Cn+1m+1​⇒ans=∑k=0n​Cnk​2kCpk​

code

#include <cstdio>
#define mod 1000000007
#define int long long
#define maxn 1000005
int n, p;
int fac[maxn], inv[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void init() {fac[0] = inv[0] = 1;for( int i = 1;i <= n;i ++ )fac[i] = fac[i - 1] * i % mod;inv[n] = qkpow( fac[n], mod - 2 );for( int i = n - 1;i;i -- )inv[i] = inv[i + 1] * ( i + 1 ) % mod;
}int C( int n, int m ) {if( n < m ) return 0;return fac[n] * inv[m] % mod * inv[n - m] % mod;
}signed main() {scanf( "%lld %lld", &n, &p );init();int ans = 0, mi = 1, MS = 1;for( int i = 0;i <= n;i ++, mi = ( mi << 1 ) % mod ) {ans = ( ans + C( n, i ) * mi % mod * MS % mod ) % mod;MS = MS * ( p - i ) % mod * qkpow( i + 1, mod - 2 ) % mod;}printf( "%lld\n", ans ); return 0;
}

D - Iroha and a Grid

description

solution

从起点到某个点(i,j)(i,j)(i,j)的方案数:一共走i−1+j−1i-1+j-1i−1+j−1步,从中选i−1i-1i−1步往下走,Ci+j−2i−1C_{i+j-2}^{i-1}Ci+j−2i−1​

对于本题,有一部分是不能走的,解决方案有两种(本质一样,出发角度不同)

  • solution1

    总方案➖从起点到被禁止区间上一行的,再强制向下走一步,最后被禁止格子到终点的方案

    必须强制向下走一步,如若不然

    则第一个红格子不合法的方案和第二个红格子的不合法方案都会包含既经过红格子1又经过红格子2的方案

  • solution2

    直接计算合法方案数,同样到被禁止上一行的时候,强制向下走一步

code

#include <cstdio>
#define maxn 200005
#define int long long
#define mod 1000000007
int n, m, A, B;
int fac[maxn], inv[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void init() {fac[0] = inv[0] = 1;for( int i = 1;i < maxn;i ++ )fac[i] = fac[i - 1] * i % mod;inv[maxn - 1] = qkpow( fac[maxn - 1], mod - 2 );for( int i = maxn - 2;i;i -- )inv[i] = inv[i + 1] * ( i + 1 ) % mod;
}int C( int n, int m ) {if( n < m ) return 0;return fac[n] * inv[m] % mod * inv[n - m] % mod;
}signed main() {init();scanf( "%lld %lld %lld %lld", &n, &m, &A, &B );int ans = 0;for( int i = B + 1;i <= m;i ++ )ans = ( ans + C( n - A + i - 2, i - 1 ) * C( m - i + A - 1, m - i ) % mod ) % mod;printf( "%lld\n", ans );return 0;
}

数论三之组合数学Ⅰ-Max-Min Sums,Binomial Coefficient is Fun,Strivore,Bubble Sort,放棋子,LOJ6671,Iroha and a Grid相关推荐

  1. MySQL查询输入三个数的和_mysql(三)(单表查询、select、where、聚合函数、count、sum、avg、MAX/MIN、分组查询、group by、having、limit)...

    单表查询 select 建个表 1.查询表中所有学生的信息 2.查询表中所有学生的姓名和对应的英语成绩 3.过滤表中重复数据 4.在所有学生分数上添加10分特长分 下面方式并没有改变底层的数据记录,这 ...

  2. Python 内建函数 max/min的高级用法

    max/min 函数 Python 中的 max/min函数是用来获取传入参数的最大值或最小值的,其运行机制都一样,所以这里主要描述 max 的运行机制以及使用方法. 最简单的用法,就是直接传入两个要 ...

  3. 9_InfluxDB常用函数(二)选择类函数(TOP() BOTTOM() FIRST() LAST() MAX() MIN() PERCENTILE())

    9.InfluxDB学习之InfluxDB常用函数(二)选择类函数 转自:http://www.linuxdaxue.com/influxdb-study-influxdb-selectors-fun ...

  4. SQL极致优化案例:利用索引特性进行max/min优化

    不要错过更多干货文章,点击上方蓝字关注我们 IS NOT NULL的优化 1. 问题提出 客户系统有这样一条SQL,脱敏后如下: SELECT NVL(MAX(T1.CREATED),SYSDATE) ...

  5. 【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  6. 理解 Math.max(min).apply 获取数组中的最大(小)值机制

    前言- 阿姆斯特朗回旋加速喷气式阿姆斯特朗炮, 还原度还真高呢 >-< 了解 apply 传入参数机制 //模拟 Math.max 方法 function Math_max(num1, n ...

  7. C++ max/min函数 你不知道的用法

    C++ max/min函数 你不知道的用法! 你听说过一个 max 函数搞定取多个数的最大值吗? 当然就是这样写: max({a, b, c}); //取a,b,c三个变量中的最大值 还可以这么写: ...

  8. c/c++ max/min 4种实现方法

    参考:https://blog.csdn.net/a_ran/article/details/74911031 1. 简单的宏实现 #define max(a,b) (((a) > (b)) ? ...

  9. Database之SQLSever:SQL命令实现四则运算、desc降序、like模糊查询、distinct去重、MAX/MIN/SUM/AVG/COUNT/GROUP/having等案例之详细攻略

    Database之SQLSever:SQL命令实现四则运算.desc降序.like模糊查询.distinct去重.MAX/MIN/SUM/AVG/COUNT/GROUP/having等案例之详细攻略 ...

最新文章

  1. 基于Pytorch和RDKit建立QSAR模型
  2. python装饰器原理-python装饰器原理与用法深入详解
  3. 七、Sqoop架构,安装和基本使用
  4. PHP实现数组中两个数的和等于给定的目标值
  5. redis——客户端
  6. h5 bootstrap 小程序模板_软件测试人员必知H5/小程序测试点
  7. 微信终端跨平台组件 mars 开源
  8. C#中的HashTable 和Dictionary对象
  9. 更改Linux Shell的提示符
  10. 多个计算机之间触发事件,相互通信的一种方法----通过文件的办法
  11. 深入浅出的etl作业调度工具taskctl
  12. python中撤销的快捷键_python常用快捷键
  13. HTML页面显示时间——网页数字时钟、钟表
  14. 【Love2d从青铜到王者】第十篇:Love2d之类和类的继承(Classes And Inheritance)
  15. 云编程那些事3 - Yahoo的烟斗
  16. 【最新】2018年注册测绘师考试测绘案例分析真题及参考答案
  17. 台湾大学教授洪士灏对产业前景的讨论
  18. 坚果云显示连接服务器失败怎么办,坚果云提示同步过程中遇到错误,怎么解决?...
  19. 带你玩转kubernetes-k8s(第54篇-Kubernetes之使用API聚合机制扩展API资源)
  20. 中兴算法挑战赛-比特派:跳高

热门文章

  1. ubuntu 没有php.ini,linux – 在Ubuntu中我对php.ini进行了更改,但没有任何反应
  2. html二级页面内容滑动,jQuery+CSS实现的网页二级下滑菜单效果
  3. html云雾效果,PS中怎么做像这样的云雾效果?(有图)?
  4. 长春工业大学计算机科学与技术录取分数,2021年长春工业大学各省各专业最低投档录取分数线统计(文科 理科)...
  5. 赛尔号什么时候支持html5,赛尔号三全能时代即将来临 你准备好了吗
  6. leedcode344. 反转字符串
  7. Java当中 报错 没有有任何类型 的外层实例可访问
  8. 考研961数据结构c语言版真题,严蔚敏数据结构C语言版考研真题库
  9. php如何判断二维数组为空,PHP判断数组为空的具体方式
  10. [JS-DOM]DOM概述