• P7245 灯光效果


    这一整场比赛质量都很高,可以去看看,link

    P7245 灯光效果

    一个点 ((i,j)) 被改变权值当且仅当 (x_{i_1}le ile x_{i_2},y_{j_1}le jle y_{j_2})

    当它总共被改变奇数次就会对答案产生 (1) 的贡献。

    显然全局只有 (m^2) 种本质不同的点,即这 (2m) 个点把整个“舞台屏幕”分成了 (m^2) 个矩形,每一个矩形内的点对答案的贡献是相同的。

    一个非常naive的想法就是枚举这些点被改变了几次权值。这个就是在右下角选一个点,左上角选一个点,这两个值对于一块区域可以 (O(1)) 计算。

    对于 ((x_{i-1},y_{j-1}),(x_i,y_j)) 这两个点组成的矩形,右下角有 ((n-i+1)(n-j+1)) 个点,左上角有 ((i-1)(j-1)) 个点。

    每一次合法的选取两个关键点有 (dfrac{inom{m^2}{2}}{2}) 种方法(就是选两个块,然后去掉左下和右上选点的情况,根据对称性刚好是一半)

    (p=dfrac{(n-i+1)(n-j+1)(i-1)(j-1)}{frac{m^2(m-1)^2}{4}}) ,即每一次改变这一块的概率。

    最容易想到的应该是算这个式子:

    [sum_{i=1}^{k}[i\%2=1]inom{k}{i}p^i(1-p)^{k-i} ]

    可惜我数学不好不会算。。。事实上这个是能算的,用二项式定理构造一玩意: (dfrac{((1-p)+p)^k-((1-p)-p)^k}{2}) 就好了。

    我这种菜鸡会垃圾做法,常数被上面那个高明做法吊锤了好几倍。

    (f_i) 表示进行了 (i) 次变换之后这块区域为 (1) 的概率。

    显然有 (f_i=(1-p)f_{i-1}+p(1-f_{i-1}))

    这个式子可以矩乘。

    我一开始推了个垃圾 (3 imes 3) 的矩阵,被卡常了。

    后来推成 (2 imes 2) 的才过掉:

    [egin{bmatrix} f_i,f_{i-1} end{bmatrix} * egin{bmatrix} 2-2p,1\ 2p-1,0 end{bmatrix} =egin{bmatrix} f_{i+1},f_{i} end{bmatrix} ]

    后来想到这玩意可以直接推通项,一个裸的一阶递推。

    (A=1-2p,B=p) ,那么 (f_i=Af_{i-1}+B)

    两边同时除掉 (A_i) ,然后搞一堆 (f_i-f_{i-1}) 的形式加起来(差分)发现是一个等比数列。推到最后应该是

    [f_n=dfrac{B(1-(frac{1}{A})^{n+1})}{1-frac{1}{A}}cdot A^{n} ]

    但是注意边界是 (f_1=p) ,所以 (f_{k-1}) 才是答案。

    原本以为常数会小很多,结果常数大了一倍。。。

    同为 (log) ,你怎么被一个带 (4) 倍常数的矩乘吊起来打??!!!

    Code(矩乘):

    #define mod 998244353
    const int N=1005;
    int n,k,m,x[N],y[N],ans,ivm;
    namespace math{
    inline int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
    inline void fmod(int&x){x-=mod,x+=x>>31&mod;}
    }
    using math::qpow;
    using math::fmod;
    
    struct Matrix{
    	int a[2][2];
    	Matrix(){memset(a,0,sizeof(a));}
    	Matrix operator * (const Matrix&t){
    		Matrix res;
    		// rep(i,0,1)rep(j,0,1)rep(k,0,1)fmod(res.a[i][j]+=1ll*a[i][k]*t.a[k][j]%mod);
    		fmod(res.a[0][0]+=1ll*a[0][0]*t.a[0][0]%mod),fmod(res.a[0][0]+=1ll*a[0][1]*t.a[1][0]%mod);
    		fmod(res.a[0][1]+=1ll*a[0][0]*t.a[0][1]%mod),fmod(res.a[0][1]+=1ll*a[0][1]*t.a[1][1]%mod);
    		fmod(res.a[1][0]+=1ll*a[1][0]*t.a[0][0]%mod),fmod(res.a[1][0]+=1ll*a[1][1]*t.a[1][0]%mod);
    		fmod(res.a[1][1]+=1ll*a[1][0]*t.a[0][1]%mod),fmod(res.a[1][1]+=1ll*a[1][1]*t.a[1][1]%mod);
    		return res;
    	}
    	void e(){a[0][0]=a[1][1]=1,a[1][0]=a[0][1]=0;}
    };
    Matrix Matrix_qpow(Matrix a,int k){
    	Matrix res;res.e();
    	for(;k;k>>=1,a=a*a)if(k&1)res=res*a;
    	return res;
    }
    
    int calc(int yx,int zs,int k){
    	int tmp=1ll*yx*zs%mod*ivm%mod;
    	Matrix tur,sta;
    	sta.a[0][0]=tmp;
    	tur.a[0][0]=mod+2-tmp*2%mod,tur.a[0][1]=1;
    	tur.a[1][0]=(tmp*2-1)%mod,tur.a[1][1]=0;
    	sta=sta*Matrix_qpow(tur,k-1);
    	return sta.a[0][0];
    }
    signed main(){
    	n=read(),m=read(),k=read(),ivm=qpow(1ll*(m*m)*(m*m-m*2+1)/4%mod,mod-2);
    	for(int i=1;i<=m;++i)x[i]=read();
    	for(int i=1;i<=m;++i)y[i]=read();
    	for(int i=1;i<=m;++i)
    		for(int j=1;j<=m;++j){
    			int num=1ll*(x[i]-x[i-1])*(y[j]-y[j-1])%mod;
    			int tmp=calc((m-i+1)*(m-j+1),(i-1)*(j-1),k);
    			fmod(ans+=1ll*num*tmp%mod);
    		}
    	cout<<ans<<'
    ';
    	return 0;
    }
    

    Code(通项)

    #define mod 998244353
    const int N=1005;
    int n,k,m,x[N],y[N],ans,ivm;
    namespace math{
    inline int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
    inline void fmod(int&x){x-=mod,x+=x>>31&mod;}
    }
    using math::qpow;
    using math::fmod;
    
    
    int calc(int yx,int zs,int k){
    	int tmp=1ll*yx*zs%mod*ivm%mod;
    	int A=mod+1-tmp*2%mod,B=tmp,iA=qpow(A,mod-2),res;
    	res=1ll*B*(1-qpow(iA,k)+mod)%mod*qpow(mod+1-iA,mod-2)%mod*qpow(A,k-1)%mod;
    	return res;
    }
    signed main(){
    	n=read(),m=read(),k=read(),ivm=qpow(1ll*(m*m)*(m*m-m*2+1)/4%mod,mod-2);
    	for(int i=1;i<=m;++i)x[i]=read();
    	for(int i=1;i<=m;++i)y[i]=read();
    	for(int i=1;i<=m;++i)
    		for(int j=1;j<=m;++j){
    			int num=1ll*(x[i]-x[i-1])*(y[j]-y[j-1])%mod;
    			if(num)fmod(ans+=1ll*num*calc((m-i+1)*(m-j+1),(i-1)*(j-1),k)%mod);
    		}
    	cout<<ans<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    Java——多线程之方法详解
    Java——深入理解Java异常体系
    Java——Java代码的执行顺序
    Java——抽象类与接口的前世今生
    存储系列之 LUN 和 LVM
    存储系列之 RAID技术原理简介
    存储系列之 硬盘接口与SCSI总线协议
    存储系列之 介质(软盘、硬盘、固态)和磁盘寻址
    Redis设计原理简介
    MySQL InnoDB索引介绍以及在线添加索引实例分析
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14226537.html
Copyright © 2020-2023  润新知