• uoj#420. 【集训队作业2018】矩形(组合数学)


    题面

    传送门

    题解

    这辣鸡题目做了咱整整三天……咱果然还是太菜了……好珂怕的推倒啊……

    首先把它变成

    [left( sum_{i = 1}^{n} sum_{j = 1}^{m} F(i, j) \, h^{im + j} ight) mod p]

    那么最后求答案的时候乘上的({1over h^{m+1}})就行了

    我们考虑对(v)(即题目中的(f_i))和(c)分别计算贡献

    (sub_1)

    对于(v_x),打个表可以发现,第(x)行第(1)列它的系数为(b),第(2)列系数为(b^2),以及第(x+i)行第(j)列的系数为({i+j-1choose j-1}a^ib^jh^{(i+x)m}h^j)

    我们对它的系数求和,就是

    [egin{aligned} cnt &=sum_{i=0}^{n-x}a^ih^{(i+x)m}sum_{j=1}^{m}{i+j-1choose j-1}b^{j}h^{j}\ &=bh^{xm+1}sum_{i=0}^{n-x}a^ih^{im}sum_{j=0}^{m-1}{i+jchoose j}b^{j}h^{j}\ end{aligned} ]

    [egin{aligned} f_n=sum_{i=0}^na^ih^{im}sum_{j=0}^{m-1}{i+jchoose j}b^{j}h^{j}\ g_n=sum_{j=0}^{m-1}{n+jchoose j}b^{j}h^{j}\ end{aligned} ]

    于是我们显然可以写出(f_n)的递推式(f_n=f_{n-1}+a^nh^{nm}g_n)

    那么我们只要能搞出(g)就可以求出(f),进而求出每个(v_x)的系数了

    那么继续推倒

    [egin{aligned} g_n &=sum_{j=0}^{m-1}{n+jchoose j}b^{j}h^{j}\ &=sum_{j=0}^{m-1}left({n+j-1choose j-1}+{n-1+jchoose j} ight)b^{j}h^{j}\ &=bhsum_{j=0}^{m-2}{n+jchoose j}b^{j}h^{j}+sum_{j=0}^{m-1}{n-1+jchoose j}b^{j}h^{j}\ &=bhleft(g_n-{n+m-1choose m-1}b^{m-1}h^{m-1} ight)+g_{n-1} end{aligned} ]

    然后就分类讨论啊,如果(bh)等于(1),就消掉(g_n),可以直接得出(g_{n-1})的式子。如果(bh)不等于(1),就移项解方程。于是

    [g_n=egin{cases} {n+mchoose m-1}&bh=1\ {g_{n-1}+{n+m-1choose m-1}b^mh^mover 1-bh}&bh eq 1 end{cases} ]

    初值分别为(m(bh=1))({1-b^mh^mover 1-bh}(bh eq 1))

    然后递推出(g),进而求出(f),对于每个(v_x)乘上(bh^{xm+1})(f_{n-x})就行了

    (sub_2)

    然后我们考虑(c)的贡献

    对于位置((x,y))((i,j)(ileq x,jleq y))上的每一个(c)都会对这一个位置有贡献,我们可以看做向下走一步乘(a),向右走一步乘(b)((x,y))(c)的系数就是从所有((i,j))走到它的所有路径的权值之和。那么这个位置上(c)的系数就是就是

    [F(x,y)=sum_{i=0}^{x-1}sum_{j=0}^{y-1}a^ib^j{i+jchoose j} ]

    总的系数就是

    [sum_{x=1}^nh^{xn}sum_{y=1}^mh^ysum_{i=0}^{x-1}sum_{j=0}^{y-1}a^ib^j{i+jchoose j} ]

    我们记(G(x,y)=h^ysum_{i=0}^{x-1}sum_{j=0}^{y-1}a^ib^j{i+jchoose j})

    和上面一样化简。

    [egin{aligned} G(x,y) &=h^ysum_{i=0}^{x-1}sum_{j=0}^{y-1}a^ib^jleft({i+j-1choose j-1}+{i-1+jchoose j} ight)\ &=h^yasum_{i=0}^{x-2}sum_{j=0}^{y-1}a^ib^j{i+jchoose j}+h^ybsum_{i=0}^{x-1}sum_{j=0}^{y-2}a^ib^j{i+jchoose j}+h^y end{aligned} ]

    注意,中间把组合数拆开来的时候,这个式子对({0choose 0})实际上是不适用的,所以我们少算了({0choose 0})的贡献,所以最后要加上(h^y)(咱因为没发现这个细节卡了好久)

    继续推倒

    [G(x,y)=aG(x-1,y)+bleft(G(x,y)-hsum_{i=0}^{x-1}a^ib^{y-1}h^{y-1}{i+y-1choose y-1} ight)+h^y ]

    我们对这个东西求一个和,也就是记(T(x)=sum_{y=1}^m G(x,y)),有

    [T(x)=aT(x-1)+bleft(T(x)-hsum_{i=0}^{x-1}a^isum_{j=0}^{m-1}b^jh^j{i+jchoose j} ight)+{h(1-h^m)over 1-h} ]

    虽然最后的(h^y)的求和还要特判一下(h=1)的情况不过想必大家都是明白的我就不写了

    中间那一大坨是什么东西啊……回过头去看看……

    (sum_{j=0}^{m-1}b^jh^j{i+jchoose j})不等于(g_i)么……

    [T(x)=aT(x-1)+bleft(T(x)-hsum_{i=0}^{x-1}a^ig_i ight)+{h(1-h^m)over 1-h} ]

    还是分类讨论,如果(b=1)我们可以直接求出(T(x-1))的通项公式,否则就可以解出(T(x))的递推公式

    然后枚举(x),每一个(x)都要让系数加上(h^{xm}T(x)),最后系数乘上(c)就行了

    搞清楚字母哪个是哪个,别跟咱一样连自己写的啥都不知道了……

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define ll long long
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=1e6+15;
    int v[N],f[N],g[N],d[N],inv[N],t[N];
    int n,m,h,P,a,b,c,res,x,y;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R ll y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
    	return res;
    }
    int calc1(){
    	int res=0,tmp;
    	if(mul(b,h)==1){
    		f[0]=g[0]=tmp=m;
    		fp(i,1,n){
    			tmp=1ll*(i+m)%P*tmp%P*inv[i+1]%P;
    			g[i]=tmp;
    		}
    	}else{
    		int p=mul(b,h),q=ksm(p,m);
    		p=ksm(dec(1,p),P-2);
    		tmp=1,f[0]=g[0]=mul(dec(1,q),p);
    		fp(i,1,n){
    			tmp=1ll*(i+m-1)%P*tmp%P*inv[i]%P;
    			g[i]=dec(g[i-1],mul(tmp,q)),g[i]=mul(g[i],p);
    		}
    	}
    	int p=1,k=mul(a,ksm(h,m));
    	fp(i,1,n)p=mul(p,k),f[i]=add(f[i-1],mul(p,g[i]));
    	int x=mul(b,h),y=ksm(h,m);
    	fp(i,1,n)x=mul(x,y),res=add(res,1ll*x*f[n-i]%P*v[i]%P);
    	return res;
    }
    int calc2(){
    	int res=0,qwq=(h==1)?m%P:1ll*h*dec(1,ksm(h,m))%P*ksm(dec(1,h),P-2)%P;
    	if(b==1){
    		int tmp=g[0],k=1,inva=ksm(a,P-2);
    		fp(i,1,n)k=mul(k,a),tmp=add(tmp,mul(k,g[i])),t[i]=mul(dec(1ll*tmp*h%P*b%P,qwq),inva);
    	}else{
    		int tmp=g[0],k=1,invb=ksm(dec(1,b),P-2);
    		fp(i,1,n){
    			t[i]=mul(a,t[i-1]);
    			t[i]=dec(t[i],1ll*b*h%P*tmp%P);
    			t[i]=add(t[i],qwq);
    			t[i]=mul(t[i],invb);
    			k=mul(k,a),tmp=add(tmp,mul(k,g[i]));
    		}
    	}
    	int g=1,k=ksm(h,m);
    	fp(i,1,n)g=mul(g,k),res=add(res,mul(g,t[i]));
    	return mul(res,c);
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	read(),n=read(),m=read(),h=read(),P=read(),a=read(),b=read(),c=read();
    	if(!h)return printf("%d
    ",add(c,mul(b,read()))),0;
    	inv[0]=inv[1]=1;fp(i,2,n+5)inv[i]=mul(P-P/i,inv[P%i]);
    	fp(i,1,n)v[i]=read();
    	x=calc1(),y=calc2();
    	res=ksm(h,m+1),res=ksm(res,P-2),res=mul(res,add(x,y));
    	printf("%d
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    Centos安装Kafka
    centos 上如何安装python3
    python+Django CRM客户关系管理系统开发(十四)--报名流程开发
    python+Django CRM客户关系管理系统开发(十三)--面包屑导航-bootstrap路径导航
    python+Django CRM客户关系管理系统开发(十二)--action功能开发
    python Django框架下,不同路径下,html页面引入静态static文件的方法
    python+Django CRM客户关系管理系统开发(十一)--删除功能开发
    多线程之 八锁。
    浅谈多线程下if和while循环不同的原因
    浅析JVM模型以及java代码运行流程
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10466783.html
Copyright © 2020-2023  润新知