【LOJ#575】【LNR#2】不等关系(容斥,动态规划,分治FFT)

题面

LOJ

题解

一个暴力\(dp\),设\(f[i][j]\)表示考虑完了前\(i\)个位置,其中最后一个数在前面所有数中排名是第\(j\)大,那么转移的时候枚举一下当前数是第几大,并且满足不等式的限制就可以了,然后拿前缀和优化一下就可以做到\(O(n^2)\)。

我们把所有连续的<看成一段,这样子题目就变成了每次要选出一段连续的上升序列,然后相邻两个连续段之间必须满足前一段的末尾要大于后一段的开头。

显然这个大于号是不好处理的,如果我们能够任意就很好做了。

这些>,即段与段之间的分割的位置的大小情况,如果至少有\(i\)个随意,方案数是\(g[i]\),那么对于答案的贡献就是\((-1)^ig[i]\)。

再考虑一个\(dp\),我们假设分割出来的所有段中,第\(i\)段的长度是\(a[i]\)。设\(f[i][j]\)表示考虑完了前\(i\)段,选出了\(j\)个上升序列的方案数,这样子就至少有\(i-j\)个位置是非法的。转移的话枚举把哪一段作为一段上升序列,那么就是:

\[f[i][j]=\sum_{k=0}^{i-1}f[k][j-1]*{n-s[k]\choose s[i]-s[k]}
\]

其中\(s\)是\(a\)的前缀和。

不难发现第二维用处不大,因为容斥系数只有\(\pm 1\),所以可以把容斥系数带进去直接带进去而不需要额外记录第二维来辅助计算。

于是转移就变成了:

\[f[i]=-\sum_{k=0}^{i-1}f[k]{n-s[k]\choose s[i]-s[k]}
\]

发现拆开之后可以卷积,然后有一项是\((s[i]-s[k])!\)不太好弄,因为\(s\)足够小,所以把\(i\)变到\(s[i]\)位置卷,这样子\(s[i]-s[k]\)就变成了\(i-k\),那么对于非\(s[i]\)的位置,把它强制弄成\(0\)。这样子拿分治\(FFT\)卷一下就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MOD 998244353
#define MAX 524288
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
int W[MAX],r[MAX];
void NTT(int *P,int opt,int len)
{
int N,l=0;for(N=1;N<len;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
{
int w=fpow(3,(MOD-1)/(i<<1));W[0]=1;
for(int k=1;k<i;++k)W[k]=1ll*W[k-1]*w%MOD;
for(int j=0,p=i<<1;j<N;j+=p)
for(int k=0;k<i;++k)
{
int X=P[j+k],Y=1ll*W[k]*P[i+j+k]%MOD;
P[j+k]=(X+Y)%MOD;P[i+j+k]=(X+MOD-Y)%MOD;
}
}
if(opt==-1)
{
reverse(&P[1],&P[N]);
for(int i=0,inv=fpow(N,MOD-2);i<N;++i)P[i]=1ll*P[i]*inv%MOD;
}
}
int jc[MAX],jv[MAX],inv[MAX];
int n,a[MAX],ans,cnt;char s[MAX];
bool book[MAX];
int A[MAX],B[MAX],f[MAX];
void CDQ(int l,int r)
{
if(l==r)
{
if(l==0)f[l]=1;
else if(!book[l])f[l]=0;
else f[l]=1ll*f[l]*(MOD-jv[n-l])%MOD;
return;
}
int mid=(l+r)>>1;
CDQ(l,mid);
for(int i=l;i<=mid;++i)A[i-l]=1ll*f[i]*jc[n-i]%MOD;
for(int i=1;i<=r-l+1;++i)B[i]=jv[i];
int N;for(N=1;N<=r-l+1+mid-l+1;N<<=1);
NTT(A,1,N);NTT(B,1,N);
for(int i=0;i<N;++i)A[i]=1ll*A[i]*B[i]%MOD;
NTT(A,-1,N);
for(int i=mid+1;i<=r;++i)f[i]=(f[i]+A[i-l])%MOD;
for(int i=0;i<N;++i)A[i]=B[i]=0;
CDQ(mid+1,r);
}
int C(int n,int m){if(n<0||m<0||n<m)return 0;return 1ll*jc[n]*jv[m]%MOD*jv[n-m]%MOD;}
int main()
{
scanf("%s",s+1);n=strlen(s+1)+1;
for(int i=1;i<n;++i)if(s[i]=='>')book[i]=true,++cnt;
inv[0]=inv[1]=jc[0]=jv[0]=1;
for(int i=2;i<=n;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%MOD;
for(int i=1;i<=n;++i)jv[i]=1ll*jv[i-1]*inv[i]%MOD;
CDQ(0,n);
/*
f[0]=1;
for(int i=1;i<=n;++i)
if(book[i])
for(int j=0;j<i;++j)
f[i]=(f[i]+MOD-1ll*f[j]*C(n-j,i-j)%MOD)%MOD;
*/
for(int i=0;i<=n;++i)ans=(ans+f[i])%MOD;
if(cnt&1)ans=(MOD-ans)%MOD;
printf("%d\n",ans);
return 0;
}

【LOJ#575】【LNR#2】不等关系(容斥,动态规划,分治FFT)的更多相关文章

  1. LOJ575. 「LibreOJ NOI Round #2」不等关系 [容斥,分治FFT]

    LOJ 思路 发现既有大于又有小于比较难办,使用容斥,把大于改成任意减去小于的. 于是最后的串就长成这样:<<?<?<??<<<?<.我们把一段连续的& ...

  2. 【洛谷5644】[PKUWC2018] 猎人杀(容斥+生成函数+分治NTT)

    点此看题面 大致题意: 有\(n\)个人相互开枪,每个人有一个仇恨度\(a_i\),每个人死后会开枪再打死另一个还活着的人,且第一枪由你打响.设当前剩余人仇恨度总和为\(k\),则每个人被打中的概率为 ...

  3. 消失之物(背包DP)(容斥或分治)

    容斥做法: 首先n^2搞出f[i][j]第i个物品,j体积的方案数. 去除每个物品贡献: 设个g[i][j]表示当i不选,j体积方案数(注意不是此时的范围相对于全局,而不是1---i) 那么我们用到一 ...

  4. [LOJ#3119][Luogu5400][CTS2019]随机立方体(容斥+DP)

    https://www.cnblogs.com/cjyyb/p/10900993.html #include<cstdio> #include<algorithm> #defi ...

  5. 【LOJ#2542】[PKUWC2018]随机游走(min-max容斥,动态规划)

    [LOJ#2542][PKUWC2018]随机游走(min-max容斥,动态规划) 题面 LOJ 题解 很明显,要求的东西可以很容易的进行\(min-max\)容斥,那么转为求集合的\(min\). ...

  6. 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)

    [LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ...

  7. LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)

    题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...

  8. 【LOJ#6374】网格(二项式反演,容斥)

    [LOJ#6374]网格(二项式反演,容斥) 题面 LOJ 要从\((0,0)\)走到\((T_x,T_y)\),每次走的都是一个向量\((x,y)\),要求\(0\le x\le M_x,0\le ...

  9. LOJ #2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)

    很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题意: 请自行阅读 题解首先我们显然要求的是几个随机变量的最大值的期望(不是期望的最大值),然后这玩意很难求 ...

随机推荐

  1. web攻击与防御技术-平台搭建与暴力破解

    平台搭建是首先安装xampp并把pikachu的压缩文件解压在HTdocs下 然后 点击后显示 安装成功 首先随便输入一些东西 然后用burpsuite抓包 对username和password字段进 ...

  2. if(response.isSuccess){}else{}的方式,如果我们由于忽略没有设置success字段的值,就可能导致

    在日常开发中,我们会经常要在类中定义布尔类型的变量,比如在给外部系统提供一个RPC接口的时候,我们一般会定义一个字段表示本次请求是否成功的. 关于这个”本次请求是否成功”的字段的定义,其实是有很多种讲 ...

  3. javascript中的toString()

    基本介绍 javascript中的toString方法是我们在写前端时经常要用的一个函数,也就是将我们的变量转换成字符串的方法. javascript中各种类型的toString方法 javascri ...

  4. Gluserfs 架构详解【译】官网

    Gluserfs详解 排版看着不舒服的,可以查看[我的简书](https://www.jianshu.com/p/0340e429431b) doc home:https://docs.gluster ...

  5. SpringBoot2.0 整合 Shiro 框架,实现用户权限管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.Shiro简介 1.基础概念 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.作为一款安全 ...

  6. (四十六)c#Winform自定义控件-水波进度条-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

  7. Web前端基础(13):JavaScript(七)

    1. BOM JavaScript基础分为三部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:文档对象模型,操作网页上的元 ...

  8. java基础(6):方法

    1. 方法 1.1 方法概述 在我们的日常生活中,方法可以理解为要做某件事情,而采取的解决办法. 如:小明同学在路边准备坐车来学校学习.这就面临着一件事情(坐车到学校这件事情)需要解决,解决办法呢?可 ...

  9. Linux-shell学习笔记1

    1.检查 /etc/shells 这个文件可以得到有多少可用的shell,一般有一下几个: /bin/sh (已经被 /bin/bash 所取代) /bin/bash (就是 Linux 默认的 sh ...

  10. python连数据库制作音乐软件

    import pymysql conn = pymysql.connect(host="localhost",user="root",password=&quo ...