首页 > 其他分享 >CF EDU163 F-组合数、范德蒙德卷积

CF EDU163 F-组合数、范德蒙德卷积

时间:2024-03-27 21:35:54浏览次数:25  
标签:EDU163 int sum CF 德蒙 sb binom fact MOD

“总感觉这题是诈骗题…”
link:https://codeforces.com/contest/1948/problem/F

[!题意]
有 \(n\) 个袋子,每个袋子有 \(a_i\) 个金币, \(b_i\) 个银币,金币的价格固定是 \(1\) ,每个银币的价格服从 \(B(1,\frac{1}{2})\) 的分布。
\(q\) 次询问,每次问一段区间 \([l,r]\) 内背包总的价值大于其他背包价值的概率。
\(1\leq n,q\leq 3\times 10^5\)
\(\sum a,\sum b\leq 10^6\)


关键其实是 \(\sum a,\sum b\leq 10^6\),比赛时没看到这个…所以根本没往那边想…(不过没看出来组合数的结果也是我不够熟悉…)

金币价值固定,假设区间内有 \(n\) 个银币,区间外有 \(m\) 个银币,则所求概率形如 $$\sum_{x=0}^n \sum_{y=0}^m \binom{n}{x}\binom{m}{y}(\frac{1}{2})^{n+m}[x-y\geq A]$$
因为 \(n+m\) 是固定值,设为 \(S\),反过来枚举 \(x-y=v\) 的值,$$\begin{aligned}\frac{1}{2^{n+m}} \sum_{v=A}^\infty \sum_{y=0}^m \binom{m}{y}\binom{S-m}{y+v}=\frac{1}{2^{n+m}} \sum_{v=A}^\infty \sum_{y=0}^m \binom{m}{m-y}\binom{S-m}{y+v}= \frac{1}{2^{m+m}} \sum_{v=A}^\infty \binom{S}{m+v}\end{aligned}$$
最后一步就是用到了范德蒙德卷积:

\[\sum_{i=0}^k \binom{n}{i}\binom{m}{k-i}=\binom{n+m}{k} \]

Q:这个式子的上界是 \(k\) ,而你求和的对象也喝范德蒙德卷积的形式不一样,上面用的 \(y\) 只求和到了 \(m\) 而不是 \(m+v\) 没问题吗(不用仔细检查一下吗)?
A:毕竟叫卷积…其实只需要check下指标的和是否固定,以及下指标是否跑遍了所有值(\(m-y\) 跑遍了 \(0\sim m\),同时如果 \(y>m\) 的话组合数是0,这并不影响恒等式的正确性)

最后答案就变成上指标固定的组合数求和了,预处理前缀和即可

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int MOD=998244353;
int ksm(int a,int b){
    int ret=1;a%=MOD;
    for(;b;b>>=1,a=(ll)a*a%MOD)if(b&1)ret=(ll)ret*a%MOD;
    return ret;
}
const int N=2e6+5;
int n,q,a[N],b[N],sa[N],sb[N],fact[N],inv_fact[N],pre[N];
int main(){
    fastio;
    fact[0]=1;
    rep(i,1,N-5)fact[i]=(ll)fact[i-1]*i%MOD;
    inv_fact[N-5]=ksm(fact[N-5],MOD-2);
    for(int i=N-5;i>=1;i--)inv_fact[i-1]=(ll)inv_fact[i]*i%MOD;
    cin>>n>>q;
    rep(i,1,n){
        cin>>a[i];
        sa[i]=sa[i-1]+a[i];
    }
    rep(i,1,n){
        cin>>b[i];
        sb[i]=sb[i-1]+b[i];
    }
    pre[0]=1;
    rep(i,1,sb[n])pre[i]=(pre[i-1]+(ll)fact[sb[n]]*inv_fact[i]%MOD*inv_fact[sb[n]-i])%MOD;
    int pw=ksm(2,sb[n]),inv_pw=ksm(pw,MOD-2);
    while(q--){
        int l,r;
        cin>>l>>r;
        int A=sa[n]-2*(sa[r]-sa[l-1])+1,y=sb[n]-(sb[r]-sb[l-1]);
        if(A+y<0)cout<<1<<' ';
        else if(A+y>sb[n])cout<<0<<' ';
        else cout<<(ll)(pw+MOD-pre[A+y-1])*inv_pw%MOD<<' ';
    }
    return 0;
}

另一个CF的题:CF785E(https://codeforces.com/contest/785/problem/E),基本会遇到一样形式的式子。

标签:EDU163,int,sum,CF,德蒙,sb,binom,fact,MOD
From: https://www.cnblogs.com/yoshinow2001/p/18100281

相关文章

  • npm ERR! path /Users/apple/.npm/_cacache/index-v5/11/77/cf18d9ab54d565b57fb3
    在使用npm时,有时候您可能会遇到类似以下错误的权限问题:npmERR!path/Users/apple/.npm/_cacache/index-v5/11/77/cf18d9ab54d565b57fb3npmERR!codeEACCESnpmERR!errno-13npmERR!syscallopennpmERR!Error:EACCES:permissiondenied,open'/Users/apple/......
  • CF1879的题解
    (一)对于第一个问题,直接搜出字符串中有多少个仅由\(0\)或\(1\)组成的串组成的。对于第二个问题,每个串只有一个能选,然后选择顺序有所不同,具体看代码。(二)AC代码。#defineintlonglong#definemd998244353usingnamespacestd;intt,s[200010];charch[200010];sign......
  • CF340B的题解
    (一)枚举对角线。然后分别找正在对角线上方的点与对角线端点构成三角形面积的最大值。和在对角线下方的点与对角线端点构成三角形面积的最大值。如果所有点都在同侧,那么不算。通过过两点直线的解析式求出另一点在直线的哪一侧。(二)AC代码。#include<bits/stdc++.h>#define......
  • CF1864C的题解
    (一)可以将\(x\)转为二进制。考虑一个数的二进制\((1\dots10\dots0)\)。其中,第一个省略号中有什么不确定,第二个省略号里都是\(0\)。易得,每个数都可以看成这种形式。那么可以每次去掉最后一位的\(1\),易证减去的数是原数的因数。最后会得到形如\((10\dots0)\),省略号中全是......
  • CF1923B的题解
    (一)注意到\(x_i\)的绝对值\(\len\)。那么统计每一个位置的血量和。先从靠近的击杀必定最优,剩余的子弹用\(sum\)存储。还是直接上代码吧。(二)AC代码。#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intt,n,k,a[300010],dis[300010],s[300010];......
  • CF1195D2的题解
    (一)虽说代码较长,但非常好理解,还是最优解(公开的就两个)。考虑对每个数单独算贡献,循环枚举与它进行运算的数的长度,然后确定那个数的位置即可,再乘以出现的数位对应的贡献,如出现在倒数第二位就乘\(10\)。难度应该不到绿。(二)AC代码。#include<bits/stdc++.h>#defineintlonglo......
  • CF1676H2的题解
    (一)题意转化为求\(i<j\)且$a_j\lea_i$的有序对\((i,j)\)数。二维偏序,容易想到用树状数组或归并排序做。(二)AC代码(树状数组)。#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intn,t,tree[200010],a[200010];intlowbit(intx){ returnx&-x;......
  • CF1904C的题解
    (一)不太好想。(我看了题解才会)当\(k>2\)时,可以选两次相同的\(i\)和\(j\)。再将生成的数做差。当\(k=1\)时,直接\(Θ(n^2)\)枚举。当\(k=2\)时,先枚举第一次的\(i\)和\(j\),再用lower_bound()实现查找第二次选择的数。时间复杂度\(Θ(n^2\log_2{n})\)。注......
  • CF1929C的题解
    (一)每次下注,要么赚\(y\times(k-1)\),要么亏\(y\)。由于不知道什么时候会输,每次都下能赚回前面所有的金额好了。第一次下\(1\),共下\(x+1\)次。(二)AC代码。#include<bits/stdc++.h>usingnamespacestd;intt,k,x,a;intmain(){ scanf("%d",&t); while(t--){ scan......
  • CF1213D1的题解
    (一)直接暴力!!!对于每一个数,枚举它能生成的数。然后对于每一个可能的答案,开长度为\(k\)的优先队列维护,同时统计操作次数和。时间复杂度为\(Θ(\log^2_2n)\)。惊讶地发现顺便把双倍经验给切了。(卡过)(二)AC代码。#include<bits/stdc++.h>usingnamespacestd;intcnt,n,k,su......