@noi.ac - 170@ 数数
@description@
求有多少对 1 ∼ n 的排列 (a, b) 满足 \(m \le \sum_{i=1}^{n}\max(ai, bi)\)。
两个方案 (a, b) 和 (a′, b′) 不同当且仅当存在 i 使得 \(ai\not =a′i\)或 \(bi\not =b'i\)。
input
一行两个整数 n, m。
output
一行一个整数表示答案。对 998244353 取模。
sample input
3 8
sample output
18
对于100%的数据,1≤n≤50,1≤m≤10^9。
@solution@
根据我多年 OI 经验,题目短的不是水就是毒瘤。
但是这一次我好像A了这道题。
看到998244353是不是感觉整个人都不好了。
可以发现 a 中元素与 b 中元素的一一对应的关系确定了 \(\sum_{i=1}^{n}\max(ai, bi)\)。
所以我们可以只统计 a 与 b 中元素对应关系合法的方案,再乘上 n! 表示全排列。
另外还可以发现,题目所给的和式其中一个上界为 n*n(可以发现这是一个不是很紧的上界,但足够了)。故当 m > n*n 时直接输出 0 就好了。
当 m <= n*n 时,可以对于所有可能的 m ,计算 \(\sum_{i=1}^{n}\max(ai, bi)=m\) 的方案数然后进行累加。
我们为了保证 max 函数的唯一性,不妨令 ai >= bi 时 max(ai, bi) = ai;ai < bi 时 max(ai, bi) = bi。
考虑 a 中的 i,它要对答案产生贡献,只能和 b 中的 1 ~ i 配对;同样,对于 b 中的 i 要产生贡献,只能和 a 中的 1 ~ i-1 配对。
于是我们可以从小到大,考虑每一个数 i 在 a 序列与 b 序列中是否会对答案产生贡献。我们只需要知道在 i 之前有多少数未被配对。
由于 a 与 b 是一一配对,所以 a 中未配对的元素个数一定等于 b 中未配对的元素个数。
由此自然得出 dp 的状态定义:dp[i][j][k] 表示考虑到 i,i 之前 a/b 中有 j 个数还未被配对,此时凑出的和为 k。
通过分类讨论 a 中的 i 是否有贡献以及 b 中的 i 是否有贡献,得到四类转移。
注意当 a 中的 i 与 b 中的 i 相匹配时,根据上文的讨论 b 中的 i 是没有贡献的。
时间复杂度 O(n^4)。
@accepted code@
#include<cstdio>
const int MOD = 998244353;
const int MAXN = 50;
int dp[MAXN + 5][MAXN + 5][MAXN*MAXN + 5];
int main() {
int n, m; scanf("%d%d", &n, &m);
if( m > n*n ) {
puts("0");
return 0;
}
int ans = 1;
for(int i=1;i<=n;i++)
ans = 1LL*i*ans%MOD;
dp[0][0][0] = 1;
for(int i=1;i<=n;i++) {
for(int j=1;j<=i;j++)
for(int k=0;k<=n*n;k++)
dp[i][j][k] = (dp[i][j][k] + dp[i-1][j-1][k])%MOD;
for(int j=0;j<i;j++)
for(int k=i;k<=n*n;k++)
dp[i][j][k] = (dp[i][j][k] + 1LL*j*dp[i-1][j][k-i]%MOD)%MOD;
for(int j=0;j<i;j++)
for(int k=i;k<=n*n;k++)
dp[i][j][k] = (dp[i][j][k] + 1LL*(j+1)*dp[i-1][j][k-i]%MOD)%MOD;
for(int j=0;j<i-1;j++)
for(int k=2*i;k<=n*n;k++)
dp[i][j][k] = (dp[i][j][k] + 1LL*(j+1)*(j+1)%MOD*dp[i-1][j+1][k-2*i]%MOD)%MOD;
}
int res = 0;
for(int i=m;i<=n*n;i++)
res = (res + dp[n][0][i])%MOD;
printf("%lld\n", 1LL*ans*res%MOD);
}
@details@
就代码而言写起来还是很愉快的,甚至不足 1kb。
然而我当时好像一不小心把 m ≤ …… 看成 m = ……
不过还好最后改过来了,不然就直接炸掉了。。。
@noi.ac - 170@ 数数的更多相关文章
- 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 682 Solved: 364 Description 我们称一 ...
- BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]
3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...
- 【BZOJ3530】数数(AC自动机,动态规划)
[BZOJ3530]数数(AC自动机,动态规划) 题面 BZOJ 题解 很套路的\(AC\)自动机+\(DP\) 首先,如果长度小于\(N\) 就不存在任何限制 直接大力\(DP\) 然后强制限制不能 ...
- bzoj [Sdoi2014]数数 AC自动机上dp
[Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1264 Solved: 636[Submit][Status][Discu ...
- [SDOI2014]数数 --- AC自动机 + 数位DP
[SDOI2014]数数 题目描述: 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串. 例如当S=(22,333,0233)时,233是幸运数,2333 ...
- [Sdoi2014]数数[数位dp+AC自动机]
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 834 Solved: 434[Submit][Status][ ...
- # NOI.AC省选赛 第五场T1 子集,与&最大值
NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...
- NOI.ac #31 MST DP、哈希
题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...
- NOI.AC NOIP模拟赛 第六场 游记
NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...
随机推荐
- maven打包时无法识别lombok中@Data生成的get set方法
开发中使用了lombok,在使用maven编译打包时发现识别不了lombok通过注解@Data在实体类中生成的get,set方法.通过在网上的一篇博客找到了解决的办法,将maven-compiler- ...
- 2019.10.22 csp-s模拟测试82 反思总结
重来重来,刚刚就当什么都没发生 今天的题属实有些迷惑,各种意义上…总之都很有难度吧.不满归不满,这套题的确不是什么没有意义的题目. 为了考验自己的学习能力记忆力,决定不写题解,扔个代码完事了 其实是懒 ...
- Python中的进程池与线程池(包含代码)
Python中的进程池与线程池 引入进程池与线程池 使用ProcessPoolExecutor进程池,使用ThreadPoolExecutor 使用shutdown 使用submit同步调用 使用su ...
- vs2015卸载、vs2008安装Visual Assist x
卸载2015 参考博文 1. 手动卸载VS2015的主要部分: win10系统: 控制面板---程序和功能--Microsoft Visual Studio 2015---更改卸载 2. 下载工具并解 ...
- 为什么要用Spring的依赖注入
最近写了一些Spring项目,用到了依赖注入,但是不知道为甚么要用,后来在知乎上看了一些大家的回答,觉得很精辟,遂简单总结一下. 主要是实现类之间的解耦,假如A类依赖B类,在实例化A类的话也要new一 ...
- PHP学习(mysqli函数)
php是一种运行在服务器端的程序语言,用于生产动态网页内容.特点:开源,简单,易上手,跨平台(windows,linux),占用资源少,尤其适合中小型应用开发.(微博,微信,论坛等等)一,搭建软件环境 ...
- 自学FPAG笔记之 " top_down “
top_town设计:在FPGA中top_down(自顶向上)是十分重要的一种编程方法,优点:使用top_down方法去写代码会使得程序看起来十分简洁,缺点:top_down写的文件会特别多. 例子: ...
- LintCode_111 爬楼梯
题目 假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部? 比如n=3,中不同的方法 返回 3 1 2 3 5 8 13... step[2] = ...
- dialog的进度条
import android.app.Activity; import android.app.ProgressDialog; import android.os.Bundle; import and ...
- 【JZOJ4746】【NOIP2016提高A组模拟9.3】树塔狂想曲
题目描述 相信大家都在长训班学过树塔问题,题目很简单求最大化一个三角形数塔从上往下走的路径和.走的规则是:(i,j)号点只能走向(i+1,j)或者(i+1,j+1).如下图是一个数塔,映射到该数塔上行 ...