• loj 3160 [NOI2019] 斗主地


    loj 3160 [NOI2019] 斗主地

    https://loj.ac/problem/3160

    UZJ0TU.png

    UZJsfJ.png

    UZJWm6.png

    Tutorial

    https://hyscere.github.io/2019/12/19/%E3%80%8CNOI2019%E3%80%8D%E6%96%97%E4%B8%BB%E5%9C%B0/

    很容易得到一个 (O(mn^2)) 的暴力,第(i)次洗牌时,设两堆牌期望分别为(x_1,x_2,cdots),(y_1,y_2,cdots),洗牌后的期望(z)

    [z_i= dfrac {1}{inom n{A_i}} (sum_{jle i} x_j inom {i-1}{j-1} inom {n-i}{A_i-j}+sum_{j le i} y_j inom {i-1}{j-1}inom{n-i}{(n-A_i)-j}) ]

    打表后发现,如果type=1,那么无论洗牌多少次,期望总是一次函数,type=2时总是二次函数

    所以我们只需要维护(x_1,x_2,x_3),每次洗牌时,用拉格朗日插值算出(y_1,y_2,y_3),然后暴力转移即可.

    对于询问也用拉格朗日插值计算答案.

    复杂度 (O(m))

    Code

    #include <cstdio>
    #include <iostream>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    #define inver(a) power(a,mod-2)
    using namespace std;
    inline char gc() {
    	static char buf[100000],*l=buf,*r=buf;
    	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
    }
    template<class T> void rd(T &x) {
    	x=0; int f=1,ch=gc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=gc();}
    	x*=f;
    }
    typedef long long ll;
    const int mod=998244353;
    int n,m,type,a[5];
    int s1[5],s2[5],s3[5],C[5][5],fac[5],inv[5];
    inline int add(int x) {return x>=mod?x-mod:x;}
    inline int sub(int x) {return x<0?x+mod:x;}
    ll power(ll x,ll y) {
    	ll re=1;
    	while(y) {
    		if(y&1) re=re*x%mod;
    		x=x*x%mod;
    		y>>=1;
    	}
    	return re;
    }
    inline int cal(int x) {
    	static int pre[5],suf[5];
    	pre[0]=1;
    	for(int i=1;i<=3;++i) pre[i]=(ll)pre[i-1]*sub(x-i)%mod;
    	suf[4]=1;
    	for(int i=3;i>=1;--i) suf[i]=(ll)suf[i+1]*sub(x-i)%mod;
    	int re=0;
    	for(int i=1;i<=3;++i) {
    		int c=(ll)pre[i-1]*suf[i+1]%mod*inv[i-1]%mod*inv[3-i]%mod*((3-i)&1?mod-1:1)%mod;
    		re=(re+(ll)c*a[i])%mod;
    	}
    	return re;
    }
    void init(int *s,int n) {
    	s[0]=1;
    	for(int i=1;i<=3;++i) s[i]=(ll)s[i-1]*(n-i+1)%mod; 
    }
    void init() {
    	fac[0]=1;
    	for(int i=1;i<=3;++i) fac[i]=(ll)fac[i-1]*i%mod;
    	inv[3]=inver(fac[3]);
    	for(int i=3;i>=1;--i) inv[i-1]=(ll)inv[i]*i%mod;
    	for(int i=0;i<=3;++i) {
    		C[i][0]=C[i][i]=1;
    		for(int j=1;j<i;++j) C[i][j]=add(C[i-1][j-1]+C[i-1][j]);
    	}
    	init(s1,n);
    	for(int i=1;i<=3;++i) s1[i]=inver(s1[i]);
    }
    int main() {
    	freopen("landlords.in","r",stdin);
    	freopen("landlords.out","w",stdout);
    	rd(n),rd(m),rd(type);
    	init();
    	for(int i=1;i<=3;++i) a[i]=type==1?i:i*i;
    	for(int i=1;i<=m;++i) {
    		static int A[5],B[5];
    		int c; rd(c);
    		for(int i=1;i<=3;++i) A[i]=i<=c?a[i]:0;
    		for(int i=1;i<=3;++i) B[i]=c+i<=n?cal(c+i):0;
    		init(s2,c),init(s3,n-c);
    		for(int i=1;i<=3;++i) {
    			a[i]=0;
    			for(int j=1;j<=3;++j) {
    				a[i]=(a[i]+(ll)A[j]*C[i-1][j-1]%mod*s1[i]%mod*s2[j]%mod*s3[i-j])%mod;
    				a[i]=(a[i]+(ll)B[j]*C[i-1][j-1]%mod*s1[i]%mod*s3[j]%mod*s2[i-j])%mod;
    			}
    		}
    	}
    	int Q; rd(Q);
    	for(int i=1;i<=Q;++i) {
    		int x; rd(x);
    		printf("%d
    ",cal(x));
    	}
    	return 0;
    }
    
  • 相关阅读:
    给未来的你——李开复2011级大学新生演讲
    李开复致信中国大学生:大学4年应是这样度过
    sublime中空格和tab的区分
    ffmpeg开发中的问题(九)
    ffmpeg开发中的问题(八)
    ffmpeg开发中出现的问题(七)
    ffmpeg开发中出现的问题(六)
    ffmpeg开发中出现的问题(五)
    ffmpeg源码学习
    ffmpeg开发出现的问题(四) ftp/rstp/ts 流输出
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13269101.html
Copyright © 2020-2023  润新知