zoukankan      html  css  js  c++  java
  • loj3120 「CTS2019 | CTSC2019」珍珠

    link

    .... 感觉自己太颓废了。。。。还是来更题解吧。。。【话说写博客会不会涨 rp 啊 qaq ?

    题意:

    有 n 个物品,每个都有一个 [1,D] 中随机的颜色,相同颜色的两个物品可以配对。现在要求至少能配 m 对,问方案数? $n,mleq 10^9,Dleq 10^5$

    题解:

    配对数量 $geq m Longleftrightarrow$ 出现奇数次的权值个数 $leq n-2m$ 。

    一个权值出现偶数次的生成函数: $frac{e^x +e^{-x}}{2}$

    一个权值出现奇数次的生成函数: $frac{e^x - e^{-x}}{2}$

    答案的式子:

    $$ egin{aligned} &n!sum_{k=0}^{n-2m} left ( frac{e^x +e^{-x}}{2} + y frac{e^x - e^{-x}}{2} ight )^D [x^n][y^k]\ =&n!left (frac12 ight )^D sum_{k=0}^{n-2m} left (e^x + e^{-x} + yleft ( e^x - e^{-x} ight ) ight )^D[x^n][y^k]\ =&n!left (frac12 ight )^D sum_{k=0}^{n-2m} left (e^x (1+y) + e^{-x}(1-y) ight )^D[x^n][y^k]\ =&n!left (frac12 ight )^D sum_{k=0}^{n-2m} sum_{i=0}^{D}inom{D}{i} left (e^{x}(1+y) ight )^i left( e^{-x}(1-y) ight )^{D-i} [x^n][y^k]\ =&n!left (frac12 ight )^D sum_{k=0}^{n-2m} sum_{i=0}^{D}inom{D}{i} e^{left (2i-D ight )x} (1+y)^i (1-y)^{D-i} [x^n][y^k]\ =&left (frac12 ight )^D sum_{i=0}^{D} inom{D}{i} (2i-D)^n sum_{k=0}^{n-2m} (1+y)^i (1-y)^{D-i} [y^k] end{aligned}$$

    这就是最后的式子。

    考虑怎么对于每个 i 快速求出后面的 $sum_{k=0}^{n-2m} (1+y)^i (1-y)^{D-i} [y^k]$ ?

    可以发现这是一个生成函数的系数前缀和。

    即 $left ( (1+y)^i (1-y)^{D-i} ight )left (1+y+y^2+y^3+... ight ) [y^{n-2m}]$ ;

    即 $left ( (1+y)^i (1-y)^{D-i} ight )left (frac{1}{1-y} ight ) [y^{n-2m}]$ 。

    可以发现当 $i eq D$ 的时候,上式 $= left ( (1+y)^i (1-y)^{D-i-1} ight )[y^{n-2m}]$ ;

    $i=D$ 的时候上式 $=sum_{k=0}^{n-2m} (1+y)^D [y^k]$ ,由于 $(1+y)^D$ 中 $y$ 不超过 D 次,所以有效的 $kleq D$ ,暴力计算即可。

    那 $i eq D$ 的时候怎么办呢?我们记 $k=n-2m$ ,$d=D-1$ ,枚举两边对 k 的贡献,即

    $$sum_{j=0}^k inom{i}{j} inom{d-i}{k-j}(-1)^{k-j}$$

    这种组合数的形式的转化当然是套路的阶乘展开啦——

    $$egin{aligned} sum_{j=0}^k frac{i!}{j!(i-j)!} cdot frac{(d-i)!}{(k-j)!(d-i-k+j)!} cdot (-1)^{k-j}\ =i!(d-i)!sum_{j=0}^k frac{(-1)^{k-j}}{j!(k-j)!} cdot frac{1}{(i-j)!(d-i-k+j)!}\ end{aligned}$$

    就是个卷积形式了, fft 即可。

    复杂度 $mathcal{O}(D log D).$

    code:

     1 #include<bits/stdc++.h>
     2 #define rep(i,x,y) for (int i=(x);i<=(y);i++)
     3 #define ll long long
     4 
     5 using namespace std;
     6 
     7 const int N=(1<<18)+10,mod=998244353,inv2=(mod+1)>>1;
     8 int D,n,m,k,d,fac[N],ifac[N],ans,invn,w[N],r[N],a[N],b[N];
     9 
    10 int ksm(int x,int y){
    11     int s=1; x=(x+mod)%mod;
    12     for (;y;y>>=1,x=(ll)x*x%mod) if (y&1) s=(ll)s*x%mod;
    13     return s;
    14 }
    15 
    16 void init(int n){
    17     fac[0]=1;
    18     rep (i,1,n) fac[i]=(ll)fac[i-1]*i%mod;
    19     ifac[n]=ksm(fac[n],mod-2);
    20     for (int i=n;i;i--) ifac[i-1]=(ll)ifac[i]*i%mod;
    21 }
    22 
    23 int C(int n,int m){
    24     if (n<m) return 0;
    25     return (ll)fac[n]*ifac[m]%mod*ifac[n-m]%mod;
    26 }
    27 
    28 inline void upd(int &x,int y){x+=y; x-=x>=mod?mod:0;}
    29 
    30 void fft_init(int &n){
    31     int len=0; while (1<<len<n) len++; n=1<<len;
    32     int G=ksm(3,(mod-1)>>len); invn=ksm(n,mod-2);
    33     w[0]=w[n]=1;
    34     rep (i,1,n-1) w[i]=(ll)w[i-1]*G%mod,r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
    35 }
    36 
    37 void fft(int *a,int all,int fl){
    38     rep (i,0,all-1) if (i<r[i]) swap(a[i],a[r[i]]);
    39     int n=2,m=1,x=all>>1;
    40     for (;n<=all;m=n,n<<=1,x>>=1)
    41         for (int i=0;i<all;i+=n)
    42             for (int k=0;k<m;k++){
    43                 int t=(ll)w[fl?all-x*k:x*k]*a[i+m+k]%mod;
    44                 a[i+m+k]=(a[i+k]+mod-t)%mod;
    45                 a[i+k]=(a[i+k]+t)%mod;
    46             }
    47     if (fl) rep (i,0,all-1) a[i]=(ll)a[i]*invn%mod;
    48 }
    49 
    50 int main(){
    51     scanf("%d%d%d",&D,&n,&m),init(D);
    52     k=min(n-2*m,D),d=D-1;
    53     rep (i,0,k) a[i]=(ll)(((k-i)&1)?mod-1:1)%mod*ifac[i]%mod*ifac[k-i]%mod;
    54     rep (i,0,d) if (d-k-i>=0) b[i]=(ll)ifac[i]%mod*ifac[d-k-i]%mod;
    55     int _n=k+d+1; fft_init(_n);
    56     fft(a,_n,0),fft(b,_n,0);
    57     rep (i,0,_n-1) a[i]=(ll)a[i]*b[i]%mod;
    58     fft(a,_n,1);
    59     rep (i,0,d) a[i]=(ll)a[i]*fac[i]%mod*fac[d-i]%mod;
    60     rep (i,0,D){
    61         int v=(ll)C(D,i)*ksm(2*i-D,n)%mod,tmp=0;
    62         if (i==D) rep (i,0,k) upd(tmp,C(D,i));
    63         else tmp=a[i];
    64         upd(ans,(ll)tmp*v%mod);
    65     }
    66     printf("%lld
    ",(ll)ans*ksm(inv2,D)%mod);
    67     return 0;
    68 }
    View Code
  • 相关阅读:
    VMware NAT 静态IP模式下上网
    无法连接虚拟设备 ide1:0
    C# ContainsKey与TryGetValue方法探究
    深入讲解以太坊的数据存储
    sqlserver之查询数据插入新建表@已存在表(oracle)
    python之列表、元祖、字典和数组的使用
    python之列表、元组、字典、数组对比
    python之ConfigParser介绍
    从业人员证券交易行为合规管理测试
    window系统自动设置时间同步脚本
  • 原文地址:https://www.cnblogs.com/bestFy/p/10887037.html
Copyright © 2011-2022 走看看