【51nod】1776 路径计数
【51nod】1776 路径计数
我们先把前两种数给排好,排好之后会有\(a + b + 1\)个空隙可以填数,我们计算有\(k\)个空隙两端都是相同字母的方案数
可以用枚举把第二种数分成几段插进去来算,设这个方案数为\(f[k]\)
然后对于一种有\(k\)个空隙的方案数,枚举剩下的\(a + b + 1 - k\)个空隙填了\(h\)个
然后计算把\(C\)和\(D\)分成\(k + h\)段的方案数就好了,记为\(g[k + h]\)
那么如何计算\(g[i]\)呢
一段要么是偶数,\(C\)和\(D\)个数相等,一段要么是奇数,\(C\)多或者\(D\)多
对于一个\(i\),强制认为\(C\)多的有\(j\)个,那么可以求出\(D\)多的是\(k\)个,剩下的必须两两配对,把剩下的\(i - j - k\),填成\(DC\)或者\(CD\),有两种方案
然后剩下的\(CD\)的对子,扔到\(i\)个区间中排列方法是唯一的,只要计算切成\(i\)段每段可以为空的方案数是多少就行了,是个组合数
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define ba 47
#define MAXN 1000005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 998244353;
int fac[10005],invfac[10005],f[5005],g[5005],pw[5005];
int a[5],N;
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
void update(int &x,int y) {
x = inc(x,y);
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
int C(int n,int m) {
if(n < m) return 0;
return mul(fac[n],mul(invfac[m],invfac[n - m]));
}
int main(){
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
fac[0] = 1;
for(int i = 1 ; i <= 10000 ; ++i) fac[i] = mul(fac[i - 1],i);
invfac[10000] = fpow(fac[10000],MOD - 2);
for(int i = 9999 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
pw[0] = 1;
for(int i = 1 ; i <= 5000 ; ++i) pw[i] = mul(pw[i - 1],2);
while(scanf("%d%d%d%d",&a[0],&a[1],&a[2],&a[3]) != EOF) {
N = a[0] + a[1] + a[2] + a[3];
if(!N) {puts("1");continue;}
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(int i = 1 ; i <= a[2] + a[3] ; ++i) {
for(int j = 0 ; j <= min(i,a[2]) ; ++j) {
if(a[3] < a[2] - j) continue;
int k = a[3] - (a[2] - j);
if(j + k > i) continue;
if(a[2] - j < i - j - k) continue;
int t = 1;
t = mul(t,C(i,j));t = mul(t,C(i - j,k));
t = mul(t,pw[i - j - k]);
int rem = a[2] - j - (i - j - k);
t = mul(t,C(rem + i - 1,i - 1));
update(g[i],t);
}
}
for(int i = 1 ; i <= a[1] ; ++i) {
int t = C(a[1] - 1,i - 1);
for(int k = max(0,i - 2) ; k <= min(a[0] - 1,i) ; ++k) {
int t0 = t;
t0 = mul(C(a[0] - 1,k),t0);t0 = mul(t0,C(2,i - k));
int p = a[0] - 1 - k + a[1] - i;
update(f[p],t0);
}
}
int ans = 0;
for(int i = 0 ; i <= a[0] + a[1] ; ++i) {
if(!f[i]) continue;
for(int h = a[0] + a[1] + 1 - i ; h >= 0 ; --h) {
int c = mul(f[i],g[i + h]);
c = mul(c,C(a[0] + a[1] + 1 - i,h));
update(ans,c);
}
}
out(ans);enter;
}
}
【51nod】1776 路径计数的更多相关文章
- 51 nod 1610 路径计数(Moblus+dp)
1610 路径计数 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 路径上所有边权的最大公约数定义为一条路径的值. 给定一个有向无环图.T次修改操作,每次修改一 ...
- 51nod 1682 中位数计数
1682 中位数计数基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 中位数定义为所有值从小到大排序后排在正中间的那个数,如果值有偶数个,通常取最中间的两个数值的平均 ...
- 蓝桥杯 历届试题 网络寻路(dfs搜索合法路径计数)
X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径 ...
- 51nod 1682 中位数计数(前缀和)
51nod 1682 中位数计数 思路: sum[i]表示到i为止的前缀和(比a[i]小的记为-1,相等的记为0,比a[i]大的记为1,然后求这些-1,0,1的前缀和): hash[sum[i]+N] ...
- 堆优化Dijkstra计算最短路+路径计数
今天考试的时候遇到了一道题需要路径计数,然而蒟蒻从来没有做过,所以在考场上真的一脸懵逼.然后出题人NaVi_Awson说明天考试还会卡SPFA,吓得我赶紧又来学一波堆优化的Dijkstra(之前只会S ...
- 【洛谷】P1176: 路径计数2【递推】
P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N),即右下角有多少种方法. 但是这个问题太简单了,所以 ...
- 牛客网 暑期ACM多校训练营(第一场)A.Monotonic Matrix-矩阵转化为格子路径的非降路径计数,Lindström-Gessel-Viennot引理-组合数学
牛客网暑期ACM多校训练营(第一场) A.Monotonic Matrix 这个题就是给你一个n*m的矩阵,往里面填{0,1,2}这三种数,要求是Ai,j⩽Ai+1,j,Ai,j⩽Ai,j+1 ,问你 ...
- 洛谷——P1176 路径计数2
P1176 路径计数2 题目描述 一个N \times NN×N的网格,你一开始在(1,1)(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N)(N,N),即右下角有 ...
- 洛谷 P1176 路径计数2
P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1, 1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N, N),即右下角有多少种方法. 但是这个问题太简单了, ...
随机推荐
- AdvanceEast源码理解
目录 文章思路 源码理解 一. 标签点形式 按顺序排列四个点,逆时针旋转,且第一个点为左上角点(刚开始选择最左边的点, 二. 标签切边 三. loss计算 四. NMS 最后说明 文章思路 大神的gi ...
- word 实现多级列表编号
- ibm 汇编
https://www.ibm.com/developerworks/cn/linux/l-assembly/index.html https://72k.us/file/4031001-328073 ...
- Cubic-bezier 曲线
cubic-bezier又称三次贝塞尔,主要是为animation生成速度曲线函数. cubic-bezier(x1,y1,x2,y2) 此图中: P0:(0,0) P1:(x1,y1) P2:(x2 ...
- PaintCode 教程:矢量图轻松转换成CoreGraphics代码
本文译自Ranwenderlich的这篇:http://www.raywenderlich.com/100281/paintcode-for-designers-getting-started Pai ...
- Telegraf+Influxdb+Grafana(Windows下本机简易监控系统搭建)
1.文件名称 telegraf-1.5.0_windows_amd64.zip influxdb-1.4.2_windows_amd64.zip grafana-4.6.3.windows-x64.z ...
- 面试题集锦---BY算法导论小组
3.7题 3.21题 1.给定能随机生成整数 1 到 5 的函数,写出能随机生成整数 1 到 7 的函数. 提示:两个random就可以有25种可能,每种可能都是等概率的 2.判断一个自然数是否是某个 ...
- 更换镜像加快python pip 安装扩展库的速度
一些镜像源: 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/ 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科 ...
- 为什么要装Tomcat?
来说一说C/S架构和B/S架构 先来说说为什么C/S框架不用对tomcat之类的部署? 其中主要的原因在与这种结构本身就是有服务器来提供服务的,客户端来使用服务. 再者说为什么B/S架构要 ...
- kill 一个名字 程序的所有进程
ps aux | grep chrome | awk '{print $2}' | xargs kill -9