传送门

解题思路

  前面的思路还是很好想的,就是要枚举最后一个\(a\)在哪出现算贡献,之后我先想的容斥,结果彻底偏了。。后来调了很久发现自己傻逼了,似乎不能容斥,终于走上正轨23333。首先可以写出一个\(O(n^2)\)的玩意,就是

\[ans=\sum\limits_{i=n}^{sum}C(n-1,i-1)*3^{sum-i}*\sum\limits_{j=max(0,i-n-m)}^{min(k,i-n)}C(i-n,j)
\]

  这个式子就是枚举\(a\)的最后一个位置\(i\),然后从前面的\(n-1\)里选\(i-1\)个\(a\),再从剩下的里面选出\(j\)个\(c\),而\(j\)还要满足不能使\(b\)超过\(m\),不能使\(c\)超过\(k\),最后后面剩下的位置随意放。这样是\(O(n^2)\)的,优化也很简单,就是发现后面的一坨对应杨辉三角同行连续一段,然后每次\(i+1\)时转移到下一行连续一段,这个随便讨论一下即可。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm> using namespace std;
typedef long long LL;
const int N=1000005;
const int MOD=1e9+7; int n,m,k,ans,fac[N],inv[N],sum; inline int fast_pow(int x,int y){
int ret=1;
for(;y;y>>=1){
if(y&1) ret=1ll*ret*x%MOD;
x=1ll*x*x%MOD;
}
return ret;
} inline int C(int x,int y){
return 1ll*fac[x]*inv[y]%MOD*inv[x-y]%MOD;
} signed main(){
scanf("%d%d%d",&n,&m,&k);
fac[0]=inv[0]=1; sum=n+m+k;
for(int i=1;i<=sum;i++) fac[i]=1ll*fac[i-1]*i%MOD;
inv[sum]=fast_pow(fac[sum],MOD-2);
for(int i=sum-1;i;i--) inv[i]=1ll*inv[i+1]*(i+1)%MOD;
// for(int i=n;i<=sum;i++){
// int now=0;
// for(int j=max(i-n-m,1ll*0);j<=min(k,i-n);j++)
// (now+=C(i-n,j))%=MOD;
// ans+=now%MOD*C(i-1,n-1)%MOD*fast_pow(3,sum-i)%MOD;
// ans%=MOD;
// }
// cout<<ans<<endl; ans=0;
if(m<k) swap(m,k); int now=1;
for(int i=n;i<=sum;i++){
if(k+n>=i) {
(ans+=1ll*C(i-1,n-1)*fast_pow(3,sum-i)%MOD*now%MOD)%=MOD;
if(k+n!=i) now=now*2%MOD;
}
else if(n+m>=i) {
now=now*2-C(i-n-1,k);
now=(now%MOD+MOD)%MOD;
(ans+=1ll*now*C(i-1,n-1)%MOD*fast_pow(3,sum-i)%MOD)%=MOD;
}
else {
now=now*2-C(i-n-1,k); now=(now%MOD+MOD)%MOD;
now=(now-C(i-n-1,i-n-m-1)+MOD)%MOD;
(ans+=1ll*now*C(i-1,n-1)%MOD*fast_pow(3,sum-i)%MOD)%=MOD;
}
}
// for(int i=n;i<=sum;i++) {
// (ans+=1ll*C(i-1,n-1)*fast_pow(2,i-n)%MOD*fast_pow(3,sum-i)%MOD)%=MOD;
// if(i==8) cout<<ans<<endl;
// if(n+k+1<=i)
// (ans-=1ll*C(i-1,n-1)*C(i-n,k+1)%MOD*fast_pow(2,i-n-k-1)%MOD*fast_pow(3,sum-i)%MOD)%=MOD;
// if(i==8) cout<<ans<<endl;
// if(n+m+1<=i)
// (ans-=1ll*C(i-1,n-1)*C(i-n,m+1)%MOD*fast_pow(2,i-n-m-1)%MOD*fast_pow(3,sum-i)%MOD)%=MOD;
// cout<<ans<<endl;
// }
// for(int i=n+m;i<sum;i++){
// (ans-=1ll*now*fast_pow(3,sum-n-m)%MOD)%=MOD;
// now=1ll*now*i%MOD; now=(now+C(n+m,i-n-m+1))%MOD;
// }
// now=1;
// for(int i=n+k;i<sum;i++){
// (ans-=1ll*now*fast_pow(3,sum-n-k)%MOD)%=MOD;
// now=1ll*now*i%MOD; now=(now+C(n+k,i-n-k+1))%MOD;
// }
printf("%d\n",(ans+MOD)%MOD);
return 0;
}

AT2070 Card Game for Three(组合数学)的更多相关文章

  1. atcoder题目合集(持续更新中)

    Choosing Points 数学 Integers on a Tree 构造 Leftmost Ball 计数dp+组合数学 Painting Graphs with AtCoDeer tarja ...

  2. 2018.09.19 atcoder Card Game for Three(组合数学)

    传送门 简单组合数学想优化想了半天啊233. 我们只需考虑翻开n张A,b张B,c张C且最后一张为A的选法数. 显然还剩下m+k−b−cm+k-b-cm+k−b−c张牌没有选. 这样的话无论前n+b+c ...

  3. 【搜索】【组合数学】zoj3841 Card

    转载自:http://blog.csdn.net/u013611908/article/details/44545955 题目大意:一副牌除掉大小王,然后有一些已经形成了序列,让你算剩下的牌能组合出多 ...

  4. Atcoder Regular Contest 061 D - Card Game for Three(组合数学)

    洛谷题面传送门 & Atcoder 题面传送门 首先考虑合法的排列长什么样,我们考虑将每次操作者的编号记录下来形成一个序列(第一次 A 操作不计入序列),那么显然这个序列中必须恰好含有 \(n ...

  5. 算法讲堂二:组合数学 & 概率期望DP

    组合数学 1. 排列组合 1. 加法原理 完成一列事的方法有 n 类,其中第 i 类方法包括\(a_i\)种不同的方法,且这些方法互不重合,则完成这件事共有 \(a_1 + a_2 + \cdots ...

  6. Lesson 3 Please send me a card

    Text Postcards always spoil my holidays. Last summer, I went to Italy. I visited museums and sat in ...

  7. iOS - Card Identification 银行卡号识别

    1.CardIO 识别 框架 GitHub 下载地址 配置 1.把框架整个拉进自己的工程,然后在 TARGETS => Build Phases => Link Binary With L ...

  8. HDOJ 4336 Card Collector

    容斥原理+状压 Card Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  9. poj 3734 Blocks 快速幂+费马小定理+组合数学

    题目链接 题意:有一排砖,可以染红蓝绿黄四种不同的颜色,要求红和绿两种颜色砖的个数都是偶数,问一共有多少种方案,结果对10007取余. 题解:刚看这道题第一感觉是组合数学,正向推了一会还没等推出来队友 ...

随机推荐

  1. php基础函数,数组

    1·字符串的处理: 2·爆炸函数(explode()): 里面填两个参数把.炸掉,在abc里 炸出来的数组 粘回去(implode()): 两个参数同上 3·截取字符串(substr()) 里面放三个 ...

  2. python读写excle

    我们可以通过python的一些模块进行excle中用例的读取,或者导出数据到excle 目录 1.安装模块 2.读excle 3.写excle 1.安装模块 python中有第三方模块可以进行excl ...

  3. hdu1159Common Subsequence——动态规划(最长公共子序列(LCS))

    Problem Description A subsequence of a given sequence is the given sequence with some elements (poss ...

  4. Python几行代码实现邮件发送

    话不多说直接进入正题 首先我们需要安装一个名为'zmail'的包,终端执行'pip install zmail'即可实现安装. 直接上代码 import zmail mail = { 'subject ...

  5. “希希敬敬对”Alpha版本发布说明

    Alpha版本的所有功能如下: 1.完成根据贴吧关键字检索的功能,通过用户输入的关键词或URL地址链接到对应的贴吧页面,并爬取到该贴吧前10页的相关数据.2.对爬取到的数据进行分析和整合,实现获取该贴 ...

  6. [Python3 填坑] 015 __str__ 与 __repr__ 的区别

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 上例子 2.2 关系与区别 Python 3.7.3 的官方文档 网上看到一个例子,运行了一下 简单地说 1. print( 坑的信息 ...

  7. Java并发编程:线程的同步

    Java并发编程:线程的同步 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...

  8. L The Digits String(没有写完,有空补)

    链接:https://ac.nowcoder.com/acm/contest/338/L来源:牛客网 Consider digits strings with length n, how many d ...

  9. 消息中间件-技术专区-RocketMQ架构原理

    RocketMQ是阿里开源的分布式消息中间件,跟其它中间件相比,RocketMQ的特点是纯JAVA实现:集群和HA实现相对简单:在发生宕机和其它故障时消息丢失率更低. 一.RocketMQ专业术语 P ...

  10. elasticsearch 基础 —— _mget取回多个文档及_bulk批量操作

    取回多个文档 Elasticsearch 的速度已经很快了,但甚至能更快. 将多个请求合并成一个,避免单独处理每个请求花费的网络延时和开销. 如果你需要从 Elasticsearch 检索很多文档,那 ...