zoukankan      html  css  js  c++  java
  • CF1086E Beautiful Matrix

    codeforces

    一般的套路显然转化按位确定

    第一行直接算有多少字典序比他小就行了。

    对于(2)(n)行,每行的总方案数就是错排数量。

    这就存在一个问题,我们无法确定当前行能放的有多少字典序比它小。

    我们发现对于第(i)行第(j)个,假如第(i-1)行前(j)个数和第(i)行前(j)个数一共有(y)个不同的数,那么在剩下的(n-j)个数中,就存在(y)个位置不受限制,也就是一共存在(n-j-y)个限制,那么现在的问题就是我们需要求出(f[i][j])表示(i)个数,存在(j)个限制的排列数。

    容易得出(f[i][j]=f[i][j-1]-f[i-1][j-1])(n)个数(n)个限制就是错排。

    现在需要考虑的问题是我们需要算出每个位置能放的比(a[i][j])小的数有多少。

    这又有两种情况:

    我们发现对于第(i)行第(j)个,假如第(i-1)行前(j)个一共有(x)个比(a[i][j])小的数字在第(i)行前(j-1)个中没有出现过。

    1、那么这个位置放这(x)个数就会导致前(j)个数一共只剩下(x-1)个数不同,也就是后(n-j)个数有(n-j-x+1)个限制

    2、假如不放这(x)个数,依然是(x)个限制

    细节貌似不多,反正我是写自闭了

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    using namespace std;
    #define rg register
    void read(int &x){
        char ch;bool ok;
        for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
        for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
    }
    const int maxn=2010,mod=998244353;bool vis[maxn],used[maxn];
    int n,a[maxn][maxn],f[maxn][maxn],fac[maxn],ans;
    int mul(int x,int y){return 1ll*x*y-1ll*x*y/mod*mod;}
    int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    int del(int x,int y){return x-y<0?x-y+mod:x-y;}
    int g[2][maxn],ff[maxn];
    #define lowbit(i) (i&(-i))
    void ins(int a,int x,int z){for(rg int i=x;i<=n;i+=lowbit(i))g[a][i]+=z;}
    int get(int a,int x){int ans=0;for(rg int i=x;i;i-=lowbit(i))ans=add(ans,g[a][i]);return ans;}
    int main(){
        read(n);fac[0]=1;
        for(rg int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
        for(rg int i=1;i<=n;i++)
    	for(rg int j=1;j<=n;j++)
    	    read(a[i][j]);
        f[0][0]=1;
        for(rg int i=1;i<=n;i++){
    	f[i][0]=fac[i];
    	for(rg int j=1;j<=i;j++)
    	    f[i][j]=del(f[i][j-1],f[i-1][j-1]);
        }
        ff[0]=1;
        for(rg int i=1;i<=n;i++)ff[i]=mul(ff[i-1],f[n][n]);
        for(rg int j=1;j<=n;j++){
    	int t=0;
    	for(rg int i=1;i<a[1][j];i++)if(!vis[i])t++;
    	ans=add(ans,mul(mul(t,fac[n-j]),ff[n-1]));
    	vis[a[1][j]]=1;
        }
        memset(vis,0,sizeof vis);
        for(rg int i=2;i<=n;i++){
    	for(rg int j=1;j<=n;j++){
    	    
    	    int t=a[i][j]-1-get(0,a[i][j]-1),h=get(1,a[i][j]-1);
    	    if(!vis[a[i-1][j]]&&a[i-1][j]<a[i][j])t--;
    	    if(!vis[a[i-1][j]])ins(1,a[i-1][j],1);vis[a[i][j]]=1;
    	    ans=add(ans,mul(add(mul(f[n-j][n-j-get(1,n)+1],h),mul(f[n-j][n-j-get(1,n)],t-h)),ff[n-i]));
    	    ins(0,a[i][j],1);
    	    if(used[a[i][j]])ins(1,a[i][j],-1);used[a[i-1][j]]=1;
    	}
    	for(rg int j=1;j<=n;j++)g[0][j]=g[1][j]=vis[j]=used[j]=0;
        }
        printf("%d
    ",ans);
    }
    
    
  • 相关阅读:
    java基础
    HDOJ(HDU).2266 How Many Equations Can You Find (DFS)
    POJ.1416 Shredding Company (DFS)
    HDOJ(HDU).2044-2049 递推专题
    HDOJ(HDU).1045 Fire Net (DFS)
    HDOJ(HDU).1258 Sum It Up (DFS)
    HDOJ(HDU).1241 Oil Deposits(DFS)
    我的ACM参赛故事
    HDOJ(HDU).1035 Robot Motion (DFS)
    HDOJ(HDU).1016 Prime Ring Problem (DFS)
  • 原文地址:https://www.cnblogs.com/lcxer/p/11556625.html
Copyright © 2011-2022 走看看