HAOI 2018 染色(容斥+NTT)

题意

https://loj.ac/problem/2527

思路

设 \(f(k)\) 为强制选择 \(k\) 个颜色出现 \(s\) 种,其余任取的方案数。

则有
\[
f(k)={m\choose k}{n\choose sk}{(sk)!\over(s!)^k}(m-k)^{n-sk}
\]
不难看出,这个方案可能包括了超过 \(k\) 种颜色,也有重复的方案,所以恰有 \(k\) 个颜色出现 \(s\) 种的方案 \(ans_k\) 满足
\[
ans_k=\sum_{i=k}^{\min(m,{n\over s})}(-1)^{i-k}{i\choose k}f(i)
\]
最终化简得到
\[
ans_k={1\over k!}\sum_{i=k}^{\min(m,{n\over s})}i!f(i)\cdot {(-1)^{i-k}\over (i-k)!}
\]
\(\text{NTT}\) 卷积即可。

做容斥题时定义出的状态本身就是有重复的,所以需要加加减减。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
using namespace std;
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int P=1004535809;
const int N=1e7+5;
const int M=1<<17|5;
namespace _Maths
{
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    void exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(!b){x=1,y=0;return;}
        exgcd(b,a%b,y,x);y-=a/b*x;
    }
    ll Pow(ll a,ll p,ll P)
    {
        ll res=1;
        for(;p>0;p>>=1,(a*=a)%=P)if(p&1)(res*=a)%=P;
        return res;
    }
    ll inv(ll a,ll P){ll x,y;exgcd(a,P,x,y);return (x%P+P)%P;}
}
using namespace _Maths;
namespace _Polynomial
{
    int A[M<<1],B[M<<1],C[M<<1];
    int w[M<<1],r[M<<1];
    void DFT(int *a,int op,int n)
    {
        FOR(i,0,n-1)if(i<r[i])swap(a[i],a[r[i]]);
        for(int i=2;i<=n;i<<=1)
            for(int j=0;j<n;j+=i)
                for(int k=0;k<i/2;k++)
                {
                    int u=a[j+k],t=(ll)w[op==1?n/i*k:(n-n/i*k)&(n-1)]*a[j+k+i/2]%P;
                    a[j+k]=(u+t)%P,a[j+k+i/2]=(u-t)%P;
                }
        if(op==-1)
        {
            int I=inv(n,P);
            FOR(i,0,n-1)a[i]=(ll)a[i]*I%P;
        }
    }
    void multiply(const int *a,const int *b,int *c,int n1,int n2)
    {
        int n=1;
        while(n<n1+n2-1)n<<=1;
        FOR(i,0,n1-1)A[i]=a[i];
        FOR(i,0,n2-1)B[i]=b[i];
        FOR(i,n1,n-1)A[i]=0;
        FOR(i,n2,n-1)B[i]=0;
        FOR(i,0,n-1)r[i]=(r[i>>1]>>1)|((i&1)*(n>>1));
        w[0]=1,w[1]=Pow(3,(P-1)/n,P);
        FOR(i,2,n-1)w[i]=(ll)w[i-1]*w[1]%P;

        DFT(A,1,n),DFT(B,1,n);
        FOR(i,0,n-1)A[i]=(ll)A[i]*B[i]%P;
        DFT(A,-1,n);
        FOR(i,0,n1+n2-2)c[i]=(A[i]+P)%P;
    }
};
int fac[N],ifac[N],f[M];
int A[M],B[M],C[M<<1];
int W[M];
int n,m,s,b;
ll ans;

ll Com(int n,int m){return (ll)fac[n]*ifac[m]%P*ifac[n-m]%P;}

int main()
{
    fac[0]=fac[1]=1;FOR(i,2,N-1)fac[i]=(ll)fac[i-1]*i%P;
    ifac[0]=ifac[1]=1;FOR(i,2,N-1)ifac[i]=(ll)(P-P/i)*ifac[P%i]%P;
    FOR(i,2,N-1)ifac[i]=(ll)ifac[i-1]*ifac[i]%P;
    scanf("%d%d%d",&n,&m,&s);
    FOR(i,0,m)scanf("%d",&W[i]);
    b=min(m,n/s);
    FOR(i,0,b)f[i]=Com(m,i)*Com(n,s*i)%P*fac[s*i]%P*Pow(ifac[s],i,P)%P*Pow(m-i,n-s*i,P)%P;
    FOR(i,0,b)A[i]=(ll)fac[i]*f[i]%P;
    FOR(i,-b,0)B[i+b]=Pow(-1,-i,P)*ifac[-i]%P;
    _Polynomial::multiply(A,B,C,b+1,b+1);
    FOR(i,0,b)(ans+=(ll)W[i]*ifac[i]%P*C[i+b]%P)%=P;
    printf("%lld\n",(ans%P+P)%P);
    return 0;
}

原文地址:https://www.cnblogs.com/Paulliant/p/10272450.html

时间: 2024-08-30 15:07:22

HAOI 2018 染色(容斥+NTT)的相关文章

HAOI2018 [HAOI2018]染色 【组合数 + 容斥 + NTT】

题目 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度为 \(N\) 的序列, 每个位置都可以被染成 \(M\) 种颜色中的某一种. 然而小 C 只关心序列的 \(N\) 个位置中出现次数恰好为 \(S\) 的颜色种数, 如果恰 好出现了 \(S\) 次的颜色有 \(K\) 种, 则小 C 会产生 \(W_k\) 的愉悦度. 小 C 希望知道对于所有可能的染色方案, 他能获得的愉悦度的和对 1004535809 取模的结果是多少. 输入格式 从

HAOI2018染色——容斥

题目大意 loj 思路 设\(f_i\)表示至少出现了i种颜色的方案数 \[ \begin{aligned} f_i&={m \choose i}\times \frac{(s\times i)!}{(s!)^{i}}\times {n\choose s\times i}\times (m-i)^{n-s\times i}\f_i&={m \choose i}\times \frac{n!}{(s!)^{i}\times (n-s\times i)!}\times (m-i)^{n-s\t

[HAOI 2018]染色

传送门 Description 一个长度为\(N\)的序列, 每个位置都可以被染成 \(M\)种颜色中的某一种. 出现次数恰好为 \(S\)的颜色种数有\(i\)种, 会产生\(w_i\)的愉悦度. 对于所有染色方案, 能获得的愉悦度的和对\(1004535809\)取模的结果. Solution? \[ ans=\sum_{i=0}^{lim} w_i\cdot num_i \] how to get \(num_i\)? \(f_i\) : the number of occurrences

[Luogu P1450] [HAOI2008]硬币购物 背包DP+容斥

题面 传送门:https://www.luogu.org/problemnew/show/P1450 Solution 这是一道很有意思的在背包里面做容斥的题目. 首先,我们可以很轻松地想到暴力做背包的做法. 就是对于每一次询问,我们都做一次背包. 复杂度O(tot*s*log(di)) (使用二进制背包优化) 显然会T得起飞. 接下来,我们可以换一种角度来思考这个问题. 首先,我们可以假设没有每个物品的数量的限制,那么这样就会变成一个很简单的完全背包问题. 至于完全背包怎么写,我们在这里就不做

4487[Jsoi2015]染色问题 容斥+组合

4487: [Jsoi2015]染色问题 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 211  Solved: 127[Submit][Status][Discuss] Description 棋盘是一个n×m的矩形,分成n行m列共n*m个小方格.现在萌萌和南南有C种不同颜色的颜料,他们希望把棋盘用这些颜料染色,并满足以下规定:1.  棋盘的每一个小方格既可以染色(染成C种颜色中的一种) ,也可以不染色.2.  棋盘的每一行至少有一个小方格被染

[TJOI2019]唱、跳、rap和篮球——NTT+生成函数+容斥

题目链接: [TJOI2019]唱.跳.rap和篮球 直接求不好求,我们考虑容斥,求出至少有$i$个聚集区间的方案数$ans_{i}$,那么最终答案就是$\sum\limits_{i=0}^{n}(-1)^i\ ans_{i}$ 那么现在只需要考虑至少有$i$个聚集区间的方案数,我们枚举这$i$个区间的起始点位置,一共有$C_{n-3i}^{i}$种方案(可以看作是刚开始先将每个区间后三个位置去掉,从剩下$n-3i$个位置中选出$i$个区间起点,然后再在每个起点后面加上三个位置). 那么剩下的$

「PKUWC2018」猎人杀(概率+容斥+分治NTT)

https://loj.ac/problem/2541 很有意思的一道题目. 直接去算这题话,因为分母会变,你会发现不管怎么样都要枚举顺序. 考虑把题目转换,变成分母不会变的,即对于一个已经删过的,我们不把它从分母中剔除,但是,每一次的选择需要一直选直到选了一个没有被删过的. 然后再考虑怎么计算,这时就可以容斥了: 1既然要最后删除,我们枚举一个集合S一定在它之后被删,其它的随意. 设\(sw\)为\(\sum_{i\in S}w[i]\),\(W=\sum_{i=1}^n w[i]\) 最后答

HDU 6397(2018多校第8场1001) Character Encoding 容斥

听了杜教的直播后知道了怎么做,有两种方法,一种构造函数(现在太菜了,听不懂,以后再补),一种容斥原理. 知识补充1:若x1,x2,.....xn均大于等于0,则x1+x2+...+xn=k的方案数是C(k+m-1,m-1)种(貌似紫书上有,记不太清了). 知识补充2:若限制条件为n(即x1,x2....xn均小于n,假设有c个违反,则把k减掉c个n(相当于把c个超过n的数也变成大于等于0的),就可以套用知识1的公式了. 则最后的答案为sum( (-1)^c * C(m , c) * C(m-1+

[ACM-ICPC 2018 沈阳网络赛] G. Spare Tire (思维+容斥)

A sequence of integer \lbrace a_n \rbrace{an?} can be expressed as: \displaystyle a_n = \left\{ \begin{array}{lr} 0, & n=0\\ 2, & n=1\\ \frac{3a_{n-1}-a_{n-2}}{2}+n+1, & n>1 \end{array} \right.an?=????0,2,23an−1?−an−2??+n+1,?n=0n=1n>1? N