传送门

解题思路

  前面的思路还是很好想的,就是要枚举最后一个\(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. Schema 与数据类型优化

    这是<高性能 MySQL(第三版)>第四章<Schema 与数据类型优化>的读书笔记. 1. 选择优化的数据类型 数据类型的选择原则: 越小越好:选择满足需求的最小类型.注意, ...

  2. Vue作用域插槽:基本用法

    一 项目结构 二 App组件 <template> <div id="app"> <!-- 子组件 --> <user v-slot:de ...

  3. Vue访问子组件实例或子元素

    1 尽管存在 prop 和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件(例如,调用子组件的方法).为了达到这个目的,你可以通过 ref 特性为这个子组件赋予一个 ID 引用 ...

  4. centos 6.x 配置 mail 发送外部邮件详解和 sendmail 使用简介

    一.mail基本配置 1.配置:vim /etc/mail.rc 在文件末尾追加以下内容: set from=@.com # 别名<123456789@163.com> set smtp= ...

  5. vs code配置C/C++开发环境

    第一步:下载 Vs Code 点击链接下载Vs Code 下载版本  并安装 https://code.visualstudio.com/ 点击 Download for Windwos 安装时  如 ...

  6. Quartz-第一篇 认识Quartz

    1.什么是Quartz Quartz是一个任务调度框架,借助Cron表达式,Quartz可以支持各种复杂的任务调度.JDK中也提供了简单的任务调度,java.util.Timer. Quartz的三大 ...

  7. Java单链表

    一.概述 二.主方法 //创建头结点 private HeroNode head = new HeroNode(-1,null,null); //计数器,用于id的自增 private static ...

  8. 微信支付公众号支付redirect_uri域名与后台配置不一致,错误码10003

    最近弄微信支付,微信支付公众号支付redirect_uri域名与后台配置不一致,错误码10003,最容易出错两个地方 1,appid 对应不到 2,开发者网页授权 填写域名 文章来自http://ww ...

  9. 70.Trapping Rain Water(容水量)

    Level:   Hard 题目描述: Given n non-negative integers representing an elevation map where the width of e ...

  10. css中一些文本属性的用法

    代码 /* text-transform用法 */ .p1 { /* 默认值 */ text-transform: none; } .p2 { /* 每个单词的首字母大写 */ text-transf ...