[FJWC2018]全排列 DP
题面
题解
(表示第一段文字导致我在考场上没看懂题……因为我以为这个定义是定义在整个排列上的,所以相似 = 相同。结果其实是可以应用在一个区间上……)
首先我们发现,2个区间相似,其实就是离散化之后相同。
观察到,相似区间的位置是没有影响的,且由于数字两两不同,所以不管相似区间内是哪些数,我们都可以将其当做一个1 ~ len的排列来计算。
因此我们可以直接枚举相似区间的长度和逆序对个数,然后按照从小到大的顺序加入下一个数,DP出方案,也就是区间个数。
设f[i][j]表示长度为i,逆序对恰好j个方案数。
因为新插入的i严格大于1 ~ i - 1,所以插入x带来的新逆序对个数为0 ~ i - 1,因此有:
\]
因此用前缀和优化一下就可以同时做到快速转移 + 逆序对至多j。
然后对于每次询问,我们枚举一下区间长度,用组合数和阶乘算一下区间放不同数字和区间放在不同位置的方案数,求和输出即可。
注意一个坑点,排列有2个,所以组合数和阶乘都要乘2次……
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define LL long long
#define AC 510
#define ac 130100
#define p 1000000007
#define maxn 500
int T, n, m, ans;
int f[AC][ac], C[AC][AC], fac[AC];
inline int read()
{
int x = 0;char c = getchar();
while(c > '9' || c < '0') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
inline void upmin(int &a, int b) {if(b < a) a = b;}
inline void upmax(int &a, int b) {if(b > a) a = b;}
inline void up(int &a, int b) {a += b; if(a >= p) a -= p;}
inline int ad(int a, int b) {return ((a + b) % p + p) % p;}
inline int mul(int a, int b) {return 1LL * a * b % p;}
inline int two(int x) {return 1LL * x * x % p;}//因为有2个排列,所以组合数和阶乘都要乘2次
void get()
{
for(R i = 0; i <= maxn; i ++) C[i][0] = 1;
for(R i = 1; i <= maxn; i ++)
for(R j = 1; j <= maxn; j ++)
up(C[i][j], C[i - 1][j - 1]), up(C[i][j], C[i - 1][j]);
fac[0] = fac[1] = 1;
for(R i = 2; i <= maxn; i ++) fac[i] = mul(fac[i - 1], i);
}
void build()
{
for(R i = 0; i <= maxn; i ++) f[i][0] = 1;//初始化
for(R i = 1; i <= maxn; i ++)//枚举数的个数
{//f[i][j] = \sum_{k = j - i + 1}^{j}{f[i - 1][k]}相当于恰好转移到恰好,而后面的sum部分就是至多,我们所需要的也是至多
int all = (i - 1) * i / 2, tmp = maxn * maxn / 2;//所以转移的时候顺便求一下前缀和就好了
for(R j = 1; j <= tmp; j ++)//枚举逆序对的个数,因为是至多j个,所以>all的也要枚举
{//因为插入第i个数最多产生i - 1的贡献,所以还需要减去一些东西(k <= j - i就不合法了,凑不到i个逆序对)
if(j <= all) f[i][j] = ad(f[i - 1][j], (j - i >= 0) ? - f[i - 1][j - i] : 0);
up(f[i][j], f[i][j - 1]);
}
}
}
void work()
{
T = read();
while(T --)
{
n = read(), m = read(), ans = 0, m = min(n * n / 2, m);//对这个取min!因为前面的DP数组只统计到这了
for(R i = 1; i <= n; i ++)
up(ans, mul(mul(mul(f[i][m], two(C[n][i])), two(fac[n - i])), (n - i + 1)));
printf("%d\n", (ans + p) % p);
}
}
int main()
{
// freopen("in.in", "r", stdin);
get();
build();
work();
// fclose(stdin);
return 0;
}
[FJWC2018]全排列 DP的更多相关文章
- [FJWC2018]全排列
题解: 考虑长度为k的时候的贡献 即取出一些元素然后给他们排个顺序然后问你有多少排法 假设排法为ans 那么应该就是$C(n,k)*C(n,k)*(n-k)!*(n-k)!*(n-k+1)*ans$ ...
- 山东省第五届ACM省赛
题目链接:http://acm.sdut.edu.cn/sdutoj/contest_show.php?contest_id=1449 相关总结:http://www.cnblogs.com/mcfl ...
- 多校7 HDU5816 Hearthstone 状压DP+全排列
多校7 HDU5816 Hearthstone 状压DP+全排列 题意:boss的PH为p,n张A牌,m张B牌.抽取一张牌,能胜利的概率是多少? 如果抽到的是A牌,当剩余牌的数目不少于2张,再从剩余牌 ...
- 子矩阵(暴搜(全排列)+DP)
子矩阵(暴搜(全排列)+DP) 一.题目 子矩阵 时间限制: 1 Sec 内存限制: 128 MB 提交: 1 解决: 1 [提交][状态][讨论版] 题目描述 给出如下定义: 1. 子矩阵:从一 ...
- hdu 1069 (DP) Monkey and Banana
题目:这里 题意: Description 一组研究人员正在设计一项实验,以测试猴子的智商.他们将挂香蕉在建筑物的屋顶,同时,提供一些砖块给这些猴子.如果猴子足够聪明,它应当能够通过合理的放置一些砖块 ...
- 【DP】组合数字
Password Attacker 题意就是给 M 个关键字,组合成 N 字符长度的结果,每一个关键字都必须在 N 位的字符中出现,有多少种可能结果. 范围 1 ≤ M ≤ N ≤ 100. 举例假设 ...
- HDU5816 Hearthstone(状压DP)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an online collec ...
- loj 1021(状压dp+记忆化搜索)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25887 题目大意:给定的一个某进制下的排列,问它的全排列有多少个能 ...
- LightOJ1158 Anagram Division(状压DP)
题目问一个数字字符串的不重复全排列有几个能被d整除. dp[S][m]表示用字符集合S构成的%d为m的数字字符串个数 dp[0][0]=0 我为人人转移,dp[S+{x}][(m*10+str[x]- ...
随机推荐
- Html+CSS 学习第二天
趁着这两天,将html和CSS基本上学了一遍,大家如果想学习的话,可以百度w3cSchool,进行学习. 基础我就不说了,直接将我做的一个登陆页面放上去.刚学完CSS,写个漂亮的登录界面恶心死我了,感 ...
- Zigbee系列(概览)
Zigbee技术特点 低速率: 数据传输速率只有20~250kb/s, 2.4GHZ提供250kb/s, 915MHz对应40kb/s, 868Mhz对应20kb/s 低功耗:睡眠模式设备使用电池供电 ...
- 获取安卓app的appPackage和appActivity
1.需要配置好android的开发环境后,打开cmd命令窗口 2.在命令窗口中输入,adb logcat>D:/log.log,抓取日志 3.运行启动app 4.查看日志log 5.搜索日志的关 ...
- 使用GitLab创建项目
- Hexo+gitment
Gitment是一个基于GitHub问题的评论系统,可以在没有任何服务器端实现的前端使用. 演示页面 中文简介 特征 入门 方法 定制 关于安全 特征 GitHub登录 Markdown / GFM支 ...
- JavaScript事件冒泡和捕获
事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件. 事件冒泡是自下而上的去触发事件. 绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获.true,事件捕获:fa ...
- 用 Python 编写的 Python 解释器
Allison是Dropbox的工程师,在那里她维护着世界上最大的由Python客户组成的网络.在Dropbox之前,她是Recurse Center的引导师, … 她在北美的PyCon做过关于Pyt ...
- Python mutilprocessing Processing 父子进程共享文件对象?
multiprocessing python多进程模块, 于是, Processing也是多进程的宠儿. 但今天讨论的问题, 似乎也能引起我们一番重视 直接上代码: 1 2 3 4 5 6 7 ...
- 分布式数据库中间件Mycat百亿级数据存储(转)
此文转自: https://www.jianshu.com/p/9f1347ef75dd 2013年阿里的Cobar在社区使用过程中发现存在一些比较严重的问题,如高并发下的假死,心跳连接的故障,只实现 ...
- phpquery 学习笔记
phpQuery是一个基于PHP的服务端开源项目,它可以让PHP开发人员轻松处理DOM文档内容,比如获取某新闻网站的头条信息.更有意思的是,它采用了jQuery的思想,你可以像使用jQuery一样处理 ...