zoukankan      html  css  js  c++  java
  • 集合 解题报告

    集合

    对于集合(S),记(min S)表示(S)中最小的元素,并定义(F(S)=A^{min S}),设([n])表示集合({1,2,dots,n})

    请求出(E(F(S)|Ssubseteq[n],|S|=k)),对(M =998244353)取模

    (1le kle n<M,1le kle 10^7,1le A <M,1le Tle 5)


    考场上并不会推...

    考虑钦定最小值,那么答案为

    [frac{sum_{i=1}^nA^iinom{n-i}{k-1}}{inom{n}{k}} ]

    显然这个复杂度需要搞到(O(k))

    [f(k)=sum_{i=1}^nA^iinom{n-i}{k-1} ]

    如果(A_i=1),那么答案为(1)

    否则

    [frac{A^i-1}{A-1}=sum_{j=0}^{i-1}A^j ]

    那么

    [egin{aligned} f(k)&=sum_{i=1}^nA^iinom{n-i}{k-1}\ &=sum_{i=1}^ninom{n-i}{k-1}((sum_{j=1}^{n-1}A^j)(A-1)+1)\ &=(A-1)sum_{j=0}^{n-1}A^jsum_{i=j+1}^ninom{n-i}{k-1}+sum_{i=1}^ninom{n-i}{k-1}\ &=(A-1)sum_{j=0}^{n-1}A^jinom{n-j}{k}+inom{n}{k}\ &=(A-1)sum_{i=1}^{n-1}A_jinom{n-j}{k}+Ainom{n}{k}\ &=(A-1)f(k+1)+Ainom{n}{k}\ &=sum_{i=k}^nA(A-1)^{i-k}inom{n}{i}\ &=A(A-1)^{-k}sum_{i=k}^n(A-1)^iinom{n}{i}\ &=A(A-1)^{-k}(A^n-sum_{i=0}^{k-1}(A-1)^iinom{n}{i}) end{aligned} ]

    最后两步用了补集转换和二项式定理把复杂度搞成(O(k)),中间有一步用了求组合数一列的东西。


    Code:

    #include <cstdio>
    #include <cctype>
    const int N=1e7+1;
    const int mod=998244353;
    template <class T>
    void read(T &x)
    {
    	x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    #define mul(a,b) (1ll*(a)*(b)%mod)
    int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
    int fac[N],inv[N];
    int main()
    {
    	freopen("set.in","r",stdin);
    	freopen("set.out","w",stdout);
    	fac[0]=1;for(int i=1;i<N;i++) fac[i]=mul(fac[i-1],i);
    	inv[N-1]=qp(fac[N-1],mod-2);
    	for(int i=N-2;~i;i--) inv[i]=mul(inv[i+1],i+1);
    	int T;read(T);
    	while(T--)
    	{
    		int n,k,a,ans=0;
    		read(n),read(k),read(a);
    		if(a==1) {puts("1");continue;}
    		for(int f1=1,f2=1,i=0;i<k;i++)
    		{
    			ans=add(ans,mul(f1,mul(f2,inv[i])));
    			f1=mul(f1,a-1);
    			f2=mul(f2,n-i);
    		}
    		ans=add(qp(a,n),mod-ans);
    		int d=inv[k];
    		for(int i=n;i>n-k;i--) d=mul(d,i);
    		ans=mul(ans,qp(d,mod-2));
    		printf("%lld
    ",mul(a,mul(qp(qp(a-1,k),mod-2),ans)));
    	}
    	return 0;
    }
    

    2019.3.21

  • 相关阅读:
    虚拟机
    10亿数中找出前1000大的数
    deepin云打印实现连接Windows打印机
    如何判断一个数是否在40亿个整数中?
    大三下学期第三周总结
    使用Jenkins构建、部署spring boot项目
    大三下学期第二周总结
    谷歌zxing 二维码生成工具
    Jbarcode 条形码生成工具
    kaptcha验证码实现,配合spring boot使用
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10572958.html
Copyright © 2011-2022 走看看