Codeforces 1085G(1086E) Beautiful Matrix $dp$+树状数组
题意
定义一个\(n*n\)的矩阵是\(beautiful\)的,需要满足以下三个条件:
1.每一行是一个排列。
2.上下相邻的两个元素的值不同。
再定义两个矩阵的字典序大的矩阵大(从左往右从上到下一个一个比较)。
给出一个\(beautiful\)的\(n*n\)的矩阵,求有多少个矩阵小于这个矩阵。
Solution
逐行计算。
\(ans=\)每行字典序比这行小的排列且与上一行相邻的两个元素值不同的排列个数*\(n\)个元素错排的方案数\(^{n-i}\)
第一行的方案数随便算,我就不说了。
另外的行大概就是逐位算。
从后往前枚举前\(i\)个数相同,树状数组维护当前位置可以填的数有几个有限制(即上一行后\(n-i+1\)中有这个数)和当前能填哪些数(即比\(a_{i,j}\)小且在当前行后\(n-i+1\)个数中出现了),不难发现有限制的数或者没限制的数都是同质的,那么就答案就是方案数乘上数的个数,问题就是有几个数有限制的错排怎么算方案数?\(dp\)一下就好了。
设\(dp_{i,j}\)表示\(i\)个数中有\(j\)个数有限制的排列的方案数。
考虑从\(dp_{i,j-1}\)转移,减去多了一个限制的数会少的方案数。
多了一个限制的数不合法的方案数?那我们就强制多的那个数不符合限制,另外数符合限制,也就是\(dp_{i-1,j-1}\)。
\(dp_{i,j}=dp_{i,j-1}-dp_{i-1,j-1}\)
如果不会推,也可以打表
\(dp_{n,n}\)的值就是\(n\)个数错排的方案数。
#include<bits/stdc++.h>
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
#define cross(i,k) for (register int i=first[k];i;i=last[i])
#define Debug(x) cerr<<#x<<"="<<(x)<<endl
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pa;
inline ll read(){
ll x=0;int ch=getchar(),f=1;
while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
if (ch=='-'){f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int N = 2010;
int n,a[N][N];
const int mod = 998244353;
int fac[N],dp[N][N],p[N];
inline void init(){
fac[0]=1;For(i,1,n) fac[i]=1ll*fac[i-1]*i%mod;
dp[1][0]=1;
For(i,2,n){
dp[i][0]=fac[i];
For(j,1,i) dp[i][j]=(dp[i][j-1]-dp[i-1][j-1]+mod)%mod;
}
p[0]=1;For(i,1,n) p[i]=1ll*p[i-1]*dp[n][n]%mod;
}
struct BIT{
int c[N],sum;
inline void clear(){sum=0,memset(c,0,sizeof c);}
inline void Add(int x){sum++;for (;x<=n;x+=x&-x) c[x]++;}
inline int Query(int x){int ans=0;for (;x;x-=x&-x) ans+=c[x];return ans;}
}t,T;
int b[N],ans;
inline void Add(int x){if (++b[x]==2) T.Add(x);}
inline void upd(int &x,int y){x+=y,(x>=mod)?x-=mod:0;}
int main(){
n=read();
For(i,1,n) For(j,1,n) a[i][j]=read();
init();int sum=0;
For(i,1,n) upd(sum,1ll*fac[n-i]*(a[1][i]-1-t.Query(a[1][i]-1))%mod),t.Add(a[1][i]);
ans=1ll*sum*p[n-1]%mod;//printf("%d\n",ans);
For(i,2,n){
t.clear(),T.clear(),sum=0,memset(b,0,sizeof b);
Dow(j,n,1){
Add(a[i][j]),Add(a[i-1][j]),t.Add(a[i][j]);
int x=T.Query(a[i][j]-1),y=t.Query(a[i][j]-1)-x,z=T.sum;
if (b[a[i-1][j]]==2&&a[i-1][j]<a[i][j]) x--;
if (b[a[i-1][j]]==2) z--;
upd(sum,1ll*x*dp[n-j][z-1]%mod),upd(sum,1ll*y*dp[n-j][z]%mod);
//printf("%d %d ",z,x*dp[n-j][z-1]);
}//puts("");
upd(ans,1ll*sum*p[n-i]%mod);
}
printf("%d\n",ans);
}
Codeforces 1085G(1086E) Beautiful Matrix $dp$+树状数组的更多相关文章
- Codeforces Gym 100269F Flight Boarding Optimization 树状数组维护dp
Flight Boarding Optimization 题目连接: http://codeforces.com/gym/100269/attachments Description Peter is ...
- Educational Codeforces Round 10 D. Nested Segments (树状数组)
题目链接:http://codeforces.com/problemset/problem/652/D 给你n个不同的区间,L或者R不会出现相同的数字,问你每一个区间包含多少个区间. 我是先把每个区间 ...
- Codeforces Gym 100114 H. Milestones 离线树状数组
H. Milestones Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descripti ...
- Codeforces - 828E DNA Evolution —— 很多棵树状数组
题目链接:http://codeforces.com/contest/828/problem/E E. DNA Evolution time limit per test 2 seconds memo ...
- Codeforces 570D TREE REQUESTS dfs序+树状数组 异或
http://codeforces.com/problemset/problem/570/D Tree Requests time limit per test 2 seconds memory li ...
- Codeforces 786C Till I Collapse(树状数组+扫描线+倍增)
[题目链接] http://codeforces.com/contest/786/problem/C [题目大意] 给出一个数列,问对于不同的k,将区间划分为几个, 每个区间出现不同元素个数不超过k时 ...
- Codeforces 946G Almost Increasing Array (树状数组优化DP)
题目链接 Educational Codeforces Round 39 Problem G 题意 给定一个序列,求把他变成Almost Increasing Array需要改变的最小元素个数. ...
- Codeforces 216D Spider's Web 树状数组+模拟
题目链接:http://codeforces.com/problemset/problem/216/D 题意: 对于一个梯形区域,假设梯形左边的点数!=梯形右边的点数,那么这个梯形为红色.否则为绿色, ...
- CodeForces - 369E Valera and Queries(树状数组)
CodeForces - 369E Valera and Queries 题目大意:给出n个线段(线段的左端点和右端点坐标)和m个查询,每个查询有cnt个点,要求给出有多少条线段包含至少其中一个点. ...
随机推荐
- javascript中用闭包递归遍历树状数组
做公司项目时,要求写一个方法,方法的参数为一个菜单数组集合和一个菜单id,菜单数组的格式为树状json,如下面所示: [{"id":28,"text":&quo ...
- Linux Kernel sys_call_table、Kernel Symbols Export Table Generation Principle、Difference Between System Calls Entrance In 32bit、64bit Linux【转】
转自:http://www.cnblogs.com/LittleHann/p/4127096.html 目录 1. sys_call_table:系统调用表 2. 内核符号导出表:Kernel-Sym ...
- Django-ORM简介
ORM简介 MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库 ORM是“对象-关系-映射”的简称 ...
- 13 JSON-RPC: a tale of interfaces
JSON-RPC: a tale of interfaces 27 April 2010 Here we present an example where Go's interfaces made i ...
- WebApi参数问题方案
原文:http://www.cnblogs.com/landeanfen/p/5337072.html
- java基础47 装饰着模式设计
1.装饰者模式 增强一个类的功能,而且还可以让这些装饰类相互装饰 2.装饰者设计模式的步骤 1.在装饰类的内部维护一个被装饰类的引用 2.让装饰者有一个共同的父类或者父接口 3.实例 packa ...
- Java流(Stream)、Scanner类
读取控制台输入 Java 的控制台输入由 System.in 完成. 为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流. ...
- 在Eclipse中导入新浪微博SDK
在Eclipse中导入新浪微博SDK 今天在看<Android开发应用实战>,全书都在讲一个android版的新浪微博客户端怎么做,于是按照书上步骤做.网上有人说这本书没有细节,我想对于小 ...
- **PHP错误Cannot use object of type stdClass as array in错误的
错误:将PHP对象类型当做了PHP数组 解决方法:用对象操作符-> 今天在PHP输出一个二维数组的时候,出现了“Fatal error: Cannot use object of type s ...
- Ubuntu 使用命令更新 Ubuntu 系统
我们都知道 Ubuntu 是一款 Linux 系统,是开源的系统,随时都在更新,所以人们都说 Linux 系统要比 Windows 系统安全.那么为了我们的电脑安全,我们如何利用 Ubuntu 命令来 ...