题目

原题目

点这里

简易题意

包裹里有无限个分布均匀且刚好 \(c\) 种颜色的巧克力,现在要依次拿 \(n\) 个出来放到桌子上。每次如果桌子上面有两种相同颜色的巧克力就会把这两个巧克力给吃掉,求最后桌子上面还有 \(m\) 个巧克力的概率。


思路分析

首先,我们考虑使用概率 \(\text{DP}\) ,似乎是可做的。

但是,由于本题数据范围限制:\(N,M\le 1000000\) ,如果再从 \(DP\) 的角度思考,时间复杂度似乎有些出乎所料了,考虑用其他办法解决此题。

本人经验之谈:

没有入手点——考虑分析题目特性,进而找到对应方法解决此题。

考虑本题的一些特性:

  • \(m\le c\) ,因为如果糖果超出了 \(c\) ,就必定有重复的颜色出现,就被吃掉了。
  • \(m\le n\) ,显然吧...
  • \(2\mid (n-m)\) ,因为被吃掉当有两块重复的巧克力。
  • 设颜色 \(i\) 的糖果被取出来的次数为 \(t_i\) 。那么,如果 \(2\mid t_i\) ,则颜色 \(i\) 最终不会生下来;反之,颜色 \(i\) 最终会剩下来。
  • 方案数共 \(c^n\) 种,显然...

考虑从这些特性入手。

对于前三个特征,似乎只是我们的骗分策略...当然,对于特征一,可以用来优化 \(DP\) ,但是还需卡常才能过。

针对特征四,似乎可以进行发散:

对于我们取出来的 \(n\) 个球,有 \(m\) 个颜色取了奇数个,剩余 \(c-m\) 个颜色取了偶数个。

有过生成函数的经验,我们似乎可以很容易列出生成函数。

对于奇数颜色

\[F(x)=\sum_{i=0}^\infty x^{2i+1}
\]

对于偶数颜色

\[G(x)=\sum_{i=0}^\infty x^{2i}
\]

如果我们按通常的方法,将他们卷起来,你就会发现,即使你 \(WA\) 穿了,这道题也做不对。

为什么?因为这道题求的是概率,但如果你就这样卷起来,其顺序是不对的。

举个栗子,取颜色的顺序为 \(112\) 与颜色顺序 \(121\) 。

这两种剩下的结果都是 \(2\) ,但是它们属于不同的方案。

我们就要先想办法将他们变成相同的方案,最后再乘以其排列 \(n!\) 。

引入指数型母函数的性质:

指数型母函数的标志函数一般为 \(\frac{x^0}{0!}+\frac{x^1}{1}+\frac{x^2}{2!}+...\) ,对于 \(\frac{x^i}{i!}\) 表示在一个方案中某个元素出现了 \(i\) 次,而不同位置的该种元素本质不同,所以在记方案数时只算作一种,所以最后结果应处以 \(i!\) 。

根据指数型母函数的定义,对于奇数的颜色,其生成函数应该为

\[F(x)=\frac{x}{1!}+\frac{x^3}{3!}+\frac{x^5}{5!}+\ldots\ldots=\sum_{i=0}^{\infty}\frac{x^{2i+1}}{(2i+1)!}
\]

同理,偶数的颜色为

\[G(x)=1+\frac{x^2}{2!}+\frac{x^4}{4!}+\ldots\ldots=\sum_{i=0}^{\infty}\frac{x^{2i}}{(2i)!}
\]

那么,答案的生成函数即为

\[H(x)=F^m(x)\cdot G^{c-m}(x)
\]

注:从此处开始,我们就开始一直处理其系数问题,而最后的排列需要在此基础上乘以 \(n!\) 。

考虑如何化简 \(H(x)\) ,想办法简化 \(F、G\) 。

分析其一般形式,令 \(A(x)=\sum_{i=0}^\infty \frac{x^i}{i!}\) 。

有 \(e^x=A(x)\) ,下面进行证明:

设 \(B(x)=e^x\) ,已知 \(e\) 的特性:

\(f(x)=e^x\) 存在任意阶导数,且 \(f^{(n)}(x)=f(x)\) 。

那么,我们考虑将 \(B(x)\) 在 \(x_0=0\) 处进行泰勒展开,那么就有

\[\begin{aligned}
B(x)&=B(0)+\frac{B'(0)}{1!}(x-0)^1+\frac{B''(0)}{2!}(x-0)^2+\frac{B'''(0)}{3!}(x-0)^3+\ldots\ldots \\
&=1+\frac{1}{1}x+\frac{1}{2!}x^2+\frac{1}{3!}x^3+\ldots\ldots \\
&=\sum_{i=0}^\infty \frac{x^i}{i!} \\
&=A(x)
\end{aligned}
\]

所以,就有 $ek=\sum_{i=0}\infty \frac{x^i}{i!} $

那么,\(e^{-k}=\sum_{i=0}^\infty \frac{x^i}{i!}(-1)^i\)

有了这个工具,我们就可以很好地表示 \(F、G\) ,显然

\[\left\{
\begin{aligned}
F(x)&=\frac{e^k-e^{-k}}{2} \\
G(x)&=\frac{e^k+e^{-k}}{2}
\end{aligned}
\right.
\]

那么就有

\[\begin{align}
H(x)&=F^m(x)G^{c-m}(x) \\
&=(\frac{e^x-e^{-x}}{2})^m\times(\frac{e^x+e^{-x}}{2})^{c-m}\tag{1} \\
&=\frac{\sum\limits_{k=0}^{m}(-1)^kC_{m}^{k}e^{(m-k)x}e^{-kx}}{2^m}\times \frac{\sum\limits_{k=0}^{c-m}C_{c-m}^{k}e^{(c-m-k)x}e^{-kx}}{2^{c-m}}\tag{2} \\
&=2^{-c}\times \sum_{i=0}^{m}(-1)^i{m\choose i}\times e^{(m-2i)x}\times \sum_{j=0}^{c-m}{c-m\choose j}\times e^{(2j-c+m)x} \\
&=2^{(-c)}\times \sum_{i=0}^{m}\sum_{j=0}^{c-m}(-1)^i{m\choose i}{c-m\choose j}\times e^{(2m-2i+2j-c)x}\\
&=2^{(-c)}\times \sum_{i=0}^{m}\sum_{j=0}^{c-m}(-1)^i{m\choose i}{c-m\choose j}\times \sum_{k=0}^{\infty}\frac{((2m-2i+2j-c)x)^k}{k!}
\end{align}
\]

其中,我们将 \((1)\) 二项式展开之后得到 \((2)\) ,然后再将其化简得到后面的算式。

出现了 \(x^k\) ,我们将它换个写法:

\[H(x)=\sum_{k=0}^\infty \frac{\sum_{i=0}^{m}\sum_{j=0}^{c-m}(-1)^i{m\choose i}{c-m\choose j}\times (2m-2i+2j-c)^k}{2^ck!}x^k
\]

那么,\(x^n\) 的系数 \(a_n\) 的值就是

\[a_n=\frac{\sum_{i=0}^{m}\sum_{j=0}^{c-m}(-1)^i{m\choose i}{c-m\choose j}\times (2m-2i+2j-c)^n}{2^cn!}
\]

由于我们处理的是系数,那么答案就是

\[\frac{a_n\times C_c^m \times n!}{c^n}
\]

而 \(a_n\) 中有一个 \(\frac{1}{n!}\) ,所以我们将 \(a_n\) 分母中的 \(n!\) 去掉,答案就变为

\[\frac{a_n'\times C_c^m}{c^n}
\]

其中

\[a_n'=a_n\times n!=\frac{\sum_{i=0}^{m}\sum_{j=0}^{c-m}(-1)^i{m\choose i}{c-m\choose j}\times (2m-2i+2j-c)^n}{2^c}
\]

代码

#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define fep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i) const int MAXN=100; inline double qkpow(double a,int n){
// printf("Now qkpow : a == %.3lf, n == %d\n",a,n);
double ret=1;
for(;n>0;n>>=1){
if(n&1)ret*=a;
a*=a;
// printf("Now n == %d, a == %.3lf, ret == %.3lf\n",n,a,ret);
}
// printf("ans == %.3lf\n",ret);
return ret;
} double C[MAXN+5][MAXN+5]; inline void init(){
C[0][0]=1;
rep(i,1,MAXN){
C[i][0]=1;
rep(j,1,i){
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
} signed main(){
#ifdef FILEOI
freopen("file.in","r",stdin);
freopen("file.out","w",stdout);
#endif
int c,n,m;
double a;
init();
while(c=qread()){
qread(n,m);a=0;
if(m>c || m>n || (n-m)&1){
puts("0.000");
continue;
}
rep(i,0,m)rep(j,0,c-m){
a+=(i&1?-1:1)*C[m][i]*C[c-m][j]*qkpow((2*m-2*i+2*j-c)*1.0/c,n);
//此处的快速幂的底数 /c 的原因是为了防止爆 double , 而我们本来就要除以 c^n , 因而我们就在 qkpow 里面处理掉了
}
a=a*C[c][m]/qkpow(2.0,c);
printf("%.3lf\n",a);
}
return 0;
}

练习题

\(\text{[HDU2056]}\) "红色病毒"问题

#include<cstdio>
#include<vector>
#include<utility>
#include<algorithm>
using namespace std; #define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define fep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
#define LL long long
#define ull unsigned long long
#define uint unsigned int
#define pii pair<int,int>
#define Endl putchar('\n')
// #define FILEOI
// #define int long long #ifdef FILEOI
#define MAXBUFFERSIZE 500000
inline char fgetc(){
static char buf[MAXBUFFERSIZE+5],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXBUFFERSIZE,stdin),p1==p2)?EOF:*p1++;
}
#undef MAXBUFFERSIZE
#define cg (c=fgetc())
#else
#define cg (c=getchar())
#endif
template<class T>inline void qread(T& x){
char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
if(f)x=-x;
}
inline int qread(){
int x=0;char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
return f?-x:x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
template<class T>void fwrit(const T x){
if(x<0)return (void)(putchar('-'),fwrit(-x));
if(x>9)fwrit(x/10);putchar(x%10^48);
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
} const int MOD=100; ull N;int T; inline int qkpow(int a,ull n){
int ret=1;
for(;n>0;n>>=1,(a*=a)%=MOD)if(n&1)(ret*=a)%=MOD;
return ret;
} signed main(){
#ifdef FILEOI
freopen("file.in","r",stdin);
freopen("file.out","w",stdout);
#endif
int cas;
while((T=qread())^(cas=0)){
while(T--){
qread(N);
printf("Case %d: ",++cas);
writc((qkpow(4,N-1)+qkpow(2,N-1))%MOD,'\n');
}
Endl;
}
return 0;
}

「题解」「POJ1322」Chocolate的更多相关文章

  1. 「ZJOI2019」&「十二省联考 2019」题解索引

    「ZJOI2019」&「十二省联考 2019」题解索引 「ZJOI2019」 「ZJOI2019」线段树 「ZJOI2019」Minimax 搜索 「十二省联考 2019」 「十二省联考 20 ...

  2. 「题解」「美团 CodeM 资格赛」跳格子

    目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...

  3. 「题解」「HNOI2013」切糕

    文章目录 「题解」「HNOI2013」切糕 题目描述 思路分析及代码 题目分析 题解及代码 「题解」「HNOI2013」切糕 题目描述 点这里 思路分析及代码 题目分析 这道题的题目可以说得上是史上最 ...

  4. 「题解」JOIOI 王国

    「题解」JOIOI 王国 题目描述 考场思考 正解 题目描述 点这里 考场思考 因为时间不太够了,直接一上来就着手暴力.但是本人太菜,居然暴力爆 000 ,然后当场自闭- 一气之下,发现对 60pts ...

  5. 【题解】「P6832」[Cnoi2020]子弦

    [题解]「P6832」[Cnoi2020]子弦第一次写月赛题解( 首先第一眼看到这题,怎么感觉要用 \(\texttt{SAM}\) 什么高科技的?结果一仔细读题,简单模拟即可. 我们不难想出,出现最 ...

  6. 「题解报告」 P3167 [CQOI2014]通配符匹配

    「题解报告」 P3167 [CQOI2014]通配符匹配 思路 *和?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配. 我们首先把原字符串分成多个以一个通 ...

  7. 「bzoj1003」「ZJOI2006」物流运输 最短路+区间dp

    「bzoj1003」「ZJOI2006」物流运输---------------------------------------------------------------------------- ...

  8. 「bzoj1925」「Sdoi2010」地精部落 (计数型dp)

    「bzoj1925」「Sdoi2010」地精部落---------------------------------------------------------------------------- ...

  9. 「BZOJ1924」「SDOI2010」 所驼门王的宝藏 tarjan + dp(DAG 最长路)

    「BZOJ1924」[SDOI2010] 所驼门王的宝藏 tarjan + dp(DAG 最长路) -------------------------------------------------- ...

  10. 「LOJ#10051」「一本通 2.3 例 3」Nikitosh 和异或(Trie

    题目描述 原题来自:CODECHEF September Challenge 2015 REBXOR 1​​≤r​1​​<l​2​​≤r​2​​≤N,x⨁yx\bigoplus yx⨁y 表示 ...

随机推荐

  1. Java中boolean类型到底占用多少字节(转载)

    来源:https://www.cnblogs.com/brucecloud/p/5509921.html 虽然 Java 虚拟机定义了 boolean 这种数据类型,但是只对它提供了非常有限的支持.在 ...

  2. Hadoop TextInputFormat

    1. TextInputFortmat TextInputFormat是默认的InputFormat.每条记录是一行输入.Key是LongWritable类型,存储该行在整个文件中的字节偏移量(不是行 ...

  3. HTML5学习(3)元素

    HTML5元素周期表 详情见:http://www.xuanfengge.com/funny/html5/element/

  4. gnuplot 让您的数据可视化

    https://www.ibm.com/developerworks/cn/linux/l-gnuplot/index.html http://blog.sciencenet.cn/blog-3733 ...

  5. P1177排序题解

    这恐怕是一道 坑最多 最经典 的题目了. 这道题有两种解题方法: 1.自己写个排序函数 这里我们用最最最最常用的快速排序: #include <iostream> #define ll l ...

  6. 关于使用阿里云MAVEN镜像仓库

    由于国内的某些不可明确的原因 国内连接google的时候十分慢,使得看github上的项目十分慢,这里我们可以修改build.gradle下的文件来使用阿里云仓库同步 会更快: // Top-leve ...

  7. Python 多任务(进程) day1(1)

    进程和程序的关系: 通俗来讲程序是死的不变的,进程是活的改变的.一个程序在没运行之前是程序,运行之后是进程 程序是一种电脑能识别的2进制代码,当你一直运行程序的时候,会出现多个进程(相当于菜谱和菜,照 ...

  8. Go同步等待组/互斥锁/读写锁

    1. 临界资源 package main import ( "fmt" "time" ) func main() { /* 临界资源: */ a := 1 go ...

  9. 【Python】一些函数

    Python 数字类型转换 有时候,我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可. int(x) 将x转换为一个整数. float(x) 将x转换到一个浮点数. ...

  10. PHPStorm设置Ctrl+滚轮调整字体大小

    1.点击左上角的File,再点击setting: 2.Editor->General,选择Change font size (Zoom) with Ctrl+Mouse Wheel: 3.点击O ...