zoukankan      html  css  js  c++  java
  • LOJ3080 「2019 集训队互测 Day 5」国际象棋

    Link
    暴力高消做法是trivial的。
    将前(2)行、第(1)列的所有变量作为自由元。
    然后从上到下、从左到右依次考虑(x_{i,j})的转移式,可以发现该转移涉及到的变量只有(x_{i+2,j+1})未被自由元线性表示。
    那么若((i+2,j+1))在棋盘内,我们就可以由该转移得到(x_{i+2,j+1})关于自由元的线性表示,否则就可以得到一个关于自由元的方程。
    最后得到(O(n+m))个数量和自由元相等的方程,高斯消元即可解出自由元的取值。
    因为所有变量都已被自由元线性表示,那么我们就可以(O(n+m))地计算出一个变量的值了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using i64=long long;
    using i128=__int128;
    const int N=207,M=607,P=998244353,dx[]={-2,-1,1,2,2,1,-1,-2},dy[]={-1,-2,-2,-1,1,2,2,1};
    int n,m,cnt,tot,deg;
    int read(){int x;scanf("%d",&x);return x;}
    void dec(int&a,int b){a-=b,a+=a>>31&P;}
    i64 pow(i64 a,int b=P-2){i64 r=1;for(;b;b>>=1,a=a*a%P)if(b&1)r=r*a%P;return r;}
    struct poly
    {
        int a[M];
        poly(){memset(a,0,sizeof a);}
        int&operator[](int x){return a[x];}
        poly operator*(i64 b){poly c;for(int k=1;k<=deg;++k)c[k]=a[k]*b%P;return c;}
        void operator-=(const poly&b){for(int k=1;k<=deg;++k)dec(a[k],b.a[k]);}
    }f[N][N],a[M];
    int main()
    {
        n=read(),m=read();i64 sum=0,p[8];
        for(int i=0;i<8;++i) sum+=(p[i]=read());
        sum=pow(sum);for(int i=0;i<8;++i) p[i]=sum*p[i]%P;
        for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(i<=2||j<=1) f[i][j][++tot]=1;
        deg=tot+1;
        for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j)
    	{
    	    f[i+2][j+1]=f[i][j],--f[i+2][j+1][tot+1];
    	    for(int o=0,x,y;o<8;++o) if(o^4) if(x=i+dx[o],y=j+dy[o],!(x<1||x>n||y<1||y>m)) f[i+2][j+1]-=(f[x][y]*p[o]);
    	    i64 inv=pow(p[4]);f[i+2][j+1]=f[i+2][j+1]*inv;
    	    if(i+2>n||j+1>m) a[++cnt]=f[i+2][j+1];
    	}
        for(int i=1;i<=tot;++i)
        {
    	if(!a[i][i]) for(int j=i+1;j<=tot;++j) if(a[j][i]) {std::swap(a[i],a[j]);break;}
    	a[i]=a[i]*pow(a[i][i]);
    	for(int j=1;j<=tot;++j) if(j!=i&&a[j][i]) a[j]-=(a[i]*a[j][i]);
        }
        for(int q=read();q;--q)
        {
    	int x=read(),y=read();i128 ans=f[x][y][tot+1];
    	for(int k=1;k<=tot;++k) ans-=1ll*f[x][y][k]*a[k][tot+1];
    	ans=(ans%P+P)%P,printf("%d
    ",(int)ans);
        }
    }
    
  • 相关阅读:
    谈谈对《镇魔曲》经济的一些看法
    谈谈对《神武2》经济的一些看法
    关于数值策划在使用Excel表时的一点想法
    游戏系统数值建模过程设计
    制作Excel工作薄目录
    制作当前表所在文件夹中所有文件的动态链接
    Excel各种tips汇总
    关于randbetween连乘的问题
    VBA实现两种方法生成任意概率分布的随机数
    Excel数值、文本相互转换
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/13043792.html
Copyright © 2011-2022 走看看