【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 路径计数的更多相关文章

  1. 51 nod 1610 路径计数(Moblus+dp)

    1610 路径计数 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题   路径上所有边权的最大公约数定义为一条路径的值. 给定一个有向无环图.T次修改操作,每次修改一 ...

  2. 51nod 1682 中位数计数

    1682 中位数计数基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 中位数定义为所有值从小到大排序后排在正中间的那个数,如果值有偶数个,通常取最中间的两个数值的平均 ...

  3. 蓝桥杯 历届试题 网络寻路(dfs搜索合法路径计数)

    X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径 ...

  4. 51nod 1682 中位数计数(前缀和)

    51nod 1682 中位数计数 思路: sum[i]表示到i为止的前缀和(比a[i]小的记为-1,相等的记为0,比a[i]大的记为1,然后求这些-1,0,1的前缀和): hash[sum[i]+N] ...

  5. 堆优化Dijkstra计算最短路+路径计数

    今天考试的时候遇到了一道题需要路径计数,然而蒟蒻从来没有做过,所以在考场上真的一脸懵逼.然后出题人NaVi_Awson说明天考试还会卡SPFA,吓得我赶紧又来学一波堆优化的Dijkstra(之前只会S ...

  6. 【洛谷】P1176: 路径计数2【递推】

    P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N),即右下角有多少种方法. 但是这个问题太简单了,所以 ...

  7. 牛客网 暑期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 ,问你 ...

  8. 洛谷——P1176 路径计数2

    P1176 路径计数2 题目描述 一个N \times NN×N的网格,你一开始在(1,1)(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N)(N,N),即右下角有 ...

  9. 洛谷 P1176 路径计数2

    P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1, 1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N, N),即右下角有多少种方法. 但是这个问题太简单了, ...

随机推荐

  1. selenium + chromeDriver的ip代理设置

    from selenium import webdriver from selenium.webdriver.chrome.options import Options import zipfile ...

  2. ACwing_789. 数的范围

    算法竞赛进阶指南上说据说只有10%的程序员能写对二分,而我这种蒟蒻..所以虽然这是一道非常基础的二分,但我觉得对我来说还是有必要写一篇博客来总结一下,也在写的过程中检验一下自己. 一开始看到这道题我还 ...

  3. java循环获取多天时间

    通过开始时间和结束时间循环获取时间: SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date star ...

  4. (转)hadoop 配置文件解释

    借鉴:https://blog.csdn.net/wangming520liwei/article/details/78923216 Hadoop 参数配置 详解 一.常用端口 组件 节点 默认端口 ...

  5. 自动化运维工具pssh、pdsh、pscp

    pssh命令是一个python编写可以在多台服务器上执行命令的工具,同时支持拷贝文件,是同类工具中很出色的,类似pdsh,个人认为相对pdsh更为简便,使用必须在各个服务器上配置好密钥认证访问. 以下 ...

  6. Bsgs模板

    模板最主要的是自己看得舒服,不会给自己留隐患,调起来比较简单,板子有得是,最主要的是改造出适合你的那一套.                  ——mzz #include<bits/stdc++ ...

  7. MySQL_JDBC_jar包的下载与使用(Windows)

    1. 下载 (1) 打开MySQL_JDBC的下载网站:https://dev.mysql.com/downloads/connector/j/ (2) 选择操作系统:Platform Indepen ...

  8. layui问题之模拟select点击事件

    一.问题 不操作页面,实现模拟select的事件,即,自动出现下拉框,自动点击下拉框的值,select文本框的值随之改变 二.经过 刚开始查看layui官方文档,发现仅仅只是有select监听事件,即 ...

  9. 项目管理工具-OmniPlan 3 for Mac

    链接:https://pan.baidu.com/s/1tp_37fHXHwJuklL1nNSwig  密码:l0sf 激活迷药(里面自带的keygen不能用,用这个好使): Name: Appked ...

  10. webdriver报不可见元素异常方法总结

    最近一直在学Selenium相关东西,学到webdriver这块,出现报不可见元素异常方法异常,后来网上找了好多相关资料都没搞定,也没看明白,最后发现是xpath中写了calss属性有问题.现在把学习 ...