description

戳我看题目哦

solution

有一道非常相似的题目

一棵树,每条边限制两个端点的大小关系(限制 a[u]>a[v]a[u]>a[v]a[u]>a[v] 或 a[u]<a[v]a[u]<a[v]a[u]<a[v])
求有多少种符合要求的排列aaa满足整棵树的限制。n<=5000n<=5000n<=5000

考虑如果所有边都是朝一个方向的话很好做
答案就是n!n!n!除以每个子树的大小
如果存在反向边的话,暴力枚举断开若干个反向边,剩下的边改为正向,然后计算答案
容斥即可。这样暴力做的复杂度是 O(2n∗n)O(2^n*n)O(2n∗n) 的
考虑 dpdpdp,f(i,j,k)f(i,j,k)f(i,j,k) 表示以 iii 为根的子树,当前 iii 所在连通块内有 jjj 个点,总共反向 kkk 条边的方案数
合并两棵子树时,如果边是正向的,那么直接合并;
否则要么断开,要么让 k+1k+1k+1 并且按照正向合并
复杂度 nnn 的若干次方
考虑最后的容斥只需要关注 kkk 的奇偶性,因此第三维完全可以省掉
即合并两棵子树时,如果边是正向则直接合并,否则值就是断开的方案减掉把边正向的方案
因此就是一个简单的树背包,复杂度 O(n2)O(n^2)O(n2)

此题只是需要将二维dpdpdp再次优化即可
设dp[i]dp[i]dp[i]表示前缀iii的合法方案数,cnt[i]cnt[i]cnt[i]表示前缀iii中>>>的个数
dp[i]i!=∑j=0i−1[s[j]=′>′](i−j)!(−1)cnt[i−1]−cnt[j]×dp[j]j!\frac{dp[i]}{i!}=\sum_{j=0}^{i-1}\frac{[s[j]='>']}{(i-j)!}(-1)^{cnt[i-1]-cnt[j]}\times \frac{dp[j]}{j!}i!dp[i]​=j=0∑i−1​(i−j)![s[j]=′>′]​(−1)cnt[i−1]−cnt[j]×j!dp[j]​
将(−1)cnt[i−1](-1)^{cnt[i-1]}(−1)cnt[i−1]提出来,剩余部分用NTTNTTNTT分治完成
有难度

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define mod 998244353
#define int long long
#define maxn 400005
int len, inv;
char s[maxn];
int cnt[maxn];
int fac[maxn], ifac[maxn], r[maxn];
int f[maxn], g[maxn], dp[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void NTT( int *c, int opt ) {for( int i = 0;i < len;i ++ )if( i < r[i] ) swap( c[i], c[r[i]] );for( int i = 1;i < len;i <<= 1 ) {int omega = qkpow( opt == 1 ? 3 : mod / 3 + 1, ( mod - 1 ) / ( i << 1 ) );for( int j = 0;j < len;j += ( i << 1 ) ) {int w = 1;for( int k = 0;k < i;k ++, w = w * omega % mod ) {int x = c[j + k], y = w * c[j + k + i] % mod;c[j + k] = ( x + y ) % mod;c[j + k + i] = ( x - y + mod ) % mod;}}}if( opt == -1 ) {int inv = qkpow( len, mod - 2 );for( int i = 0;i < len;i ++ )c[i] = c[i] * inv % mod;}
}void solve( int L, int R ) {if( L == R ) {if( ! L ) dp[L] = 1;else dp[L] = cnt[L] & 1 ? mod - dp[L] : dp[L];//单独提出来 return;}int mid = ( L + R ) >> 1;solve( L, mid );len = 1; int l = 0;while( len <= R - L + 1 + mid - L ) len <<= 1, l ++;for( int i = 0;i < len;i ++ )r[i] = ( r[i >> 1] >> 1 ) | ( ( i & 1 ) << ( l - 1 ) );for( int i = 0;i <= mid - L;i ++ )if( s[i + L] == '<' && i + L != 0 ) f[i] = 0;else f[i] = cnt[i + L] & 1 ? dp[i + L] : mod - dp[i + L];//注意奇偶转换 for( int i = mid - L + 1;i < len;i ++ ) f[i] = 0;for( int i = 0;i <= R - L + 1;i ++ ) g[i] = ifac[i];for( int i = R - L + 2;i < len;i ++ ) g[i] = 0;NTT( f, 1 );NTT( g, 1 );for( int i = 0;i < len;i ++ ) f[i] = f[i] * g[i] % mod;NTT( f, -1 );for( int i = mid + 1;i <= R;i ++ ) dp[i] = ( dp[i] + f[i - L] ) % mod;solve( mid + 1, R );
}signed main() {scanf( "%s", s + 1 );    int n = strlen( s + 1 );s[++ n] = '>';fac[0] = 1;for( int i = 1;i <= n;i ++ )fac[i] = fac[i - 1] * i % mod;ifac[n] = qkpow( fac[n], mod - 2 );for( int i = n - 1;~ i;i -- )ifac[i] = ifac[i + 1] * ( i + 1 ) % mod;for( int i = 1;i <= n;i ++ )cnt[i] = cnt[i - 1] + ( s[i] == '>' );solve( 0, n );printf( "%lld\n", dp[n] * fac[n] % mod );return 0;
}

「LibreOJ NOI Round #2」不等关系 (dp+NTT分治)相关推荐

  1. LOJ#510. 「LibreOJ NOI Round #1」北校门外的回忆(线段树)

    题面 传送门 题解 感谢\(@M\_sea\)的代码我总算看懂题解了-- 这个操作的本质就是每次把\(x\)的\(k\)进制最低位乘\(2\)并进位,根据基本同余芝士如果\(k\)是奇数那么最低位永远 ...

  2. 【LOJ574】「LibreOJ NOI Round #2」黄金矿工

    [题目链接] 点击打开链接 [思路要点] 可参考 官方题解 . 以下为笔者个人的见解,方便起见,下称矿工为老鼠,金矿为洞. 我们可以对洞的权值加上深度,老鼠的权值减去深度,从而不需要考虑树的边权. 考 ...

  3. 【LOJ573】「LibreOJ NOI Round #2」单枪匹马(矩阵乘法)

    传送门 题解: 注意到分子分母每次无非就是交换位置然后分母加上分子的若干倍. 把这个转移写成矩阵的形式,求个逆,维护一下矩阵和矩阵的逆的前缀积就行了. 代码: #include<bits/std ...

  4. 「LibreOJ NOI Round #2」单枪匹马

    题目 通过这道题成功发现我不会矩乘 答案是一个连分数,看起来不像是一般的数据结构能做的样子,设\(x_{l,r},y_{l,r}\)分别表示\([l,r]\)询问的分子和分母 于是有 \[\frac{ ...

  5. LOJ #573. 「LibreOJ NOI Round #2」单枪匹马 线段树

    $f$ 函数暴力计算的话是 $O(n)$ 的(用一个 $\frac{x}{y}$ 来保存每一步计算结果,然后依次合并) 我们将一段区间的结果写成 $\frac{ax+by}{cx+dy}$ 的形式,初 ...

  6. 【LOJ573】「LibreOJ NOI Round #2」单枪匹马

    [题目链接] 点击打开链接 [思路要点] 见 官方题解 .(反正也是我写的) 时间复杂度 O(N+M)O(N+M)O(N+M) . [代码] #include<bits/stdc++.h> ...

  7. LOJ #510. 「LibreOJ NOI Round #1」北校门外的回忆(倍增+动态开点线段树)

    题目 这个题是一个精彩的分析性质区间离散的问题 真的详细 维护链真的一绝. LOJ\rm LOJLOJ最短ACCode\rm AC \ CodeAC Code #include<bits/std ...

  8. 「LibreOJ NOIP Round #1」旅游路线

    「LibreOJ NOIP Round #1」旅游路线 题目链接 做法: 首先肯定要预处理些东西,来使单词询问达到\(o(logn)\)或者\(o(1)\)的复杂度,又因为距离这个东西的范围太大,我们 ...

  9. 【LibreOJ】#541. 「LibreOJ NOIP Round #1」七曜圣贤

    [题意]一开始车上有编号为0~a的红茶,过程中出现的红茶编号仅有[0,b),有三种操作: 1.买进编号未在车上出现过的红茶. 2.丢掉车上指定编号的红茶. 3.将最早丢出去的红茶捡回来. 每次操作后求 ...

最新文章

  1. 苹果电脑安装python3密码_mac系统安装Python3初体验
  2. can t connect to mysql server on ‘localhost‘解决方法
  3. 得到 ip/掩码 的起始结束地址
  4. 样式处理——提取样式文件
  5. urlencode urldecode
  6. [note]浏览器兼容性(embed标签、字体兼容相关
  7. WARNING: cell0 mapping not found - not syncing cell0
  8. 推荐一款文件搜索神器Everything!
  9. [转载] 新兵训练营系列课程——海量数据存储基础
  10. 论文浅尝 - AAAI2020 | 多模态基准指导的多模态自动文摘
  11. secureCRT 如何上传下载文件
  12. python是什么意思怎么读-python怎么读,python是什么意思
  13. html怎么将背景图片旋转,css怎么旋转图片?
  14. 【零基础学Python】Day10 Python解释器
  15. Openwrt Web gui LUCI 流程浅析
  16. 用计算机打字教案,教学设计-有趣的打字练习游戏
  17. ChatGPT时代,推荐几个宝藏公众号!
  18. 开学“收心”指南来了
  19. Maven发布轻量二方包
  20. CISCO交换机配置命令及释义

热门文章

  1. 数学无用论??我们欠孩子真正的数学阅读
  2. 风靡全球的人工智能,如何赶上这班车?
  3. 烧录imx6需要的linux空间,IMX6Q学习笔记——开发板的Linux系统更新和烧录
  4. 父与子一起学python3,父与子的编程之旅 与小卡特一起学Python 第3版(全彩印刷)...
  5. 金蝶凭证序时簿在哪_来了!金蝶日常账务处理大全
  6. mysql权限create细化_mysql权限精细化分配-阿里云开发者社区
  7. Java中关于省略作用域报错问题分析
  8. [MySQL基础]MySQL语法规范介绍
  9. exceptionhandler注解_SpringMVC 中 @ControllerAdvice 注解的三种使用场景!
  10. android 按钮 菜单,(期末要考啊)Android的menu(菜单)按钮的使用