[Hackerrank 101 Hack 43&& MenciOJ P321] K-Inversion Permutations
来源:互联网 发布:算法谜题 百度云 编辑:程序博客网 时间:2024/05/29 11:13
题目链接(上面是MenciOJ,下面是Hackerrank ):
https://ly.men.ci/problem/321
https://www.hackerrank.com/contests/101hack43/challenges/k-inversion-permutations
其实还有一个bzoj2431也是一样的题目,但是数据范围更小,允许O(nk)的平方级算法。
题意:给出n,k,求逆序对数为k的1-n的排列的数量. n,k<=10^5.
题解:先来考虑一下bzoj2431的做法,这个做法是O(nk)的,
考虑一下dp:dp[i][j]表示i个数形成排列,逆序对数为j的方案数,
dp转移为:dp[i][j]=sigma(dp[i-1][j-k],k=0..min(j,i-1)).
前缀和优化一下即可得到O(nk)的解法。
dp方程解释:对于前i个数,我们不关心它们的具体大小,只关心相对大小,
因为相对大小就可以确定一个序列的逆序对数量,而指数级别的状态数被减少到了平方级别,
这样就可以把它们离散到一个[1,i]的区间上,通过枚举下一个位置选择的数在这个[1,i]排列中的位置(也就是与前(i-1)个数的相对大小)进行转移。
但是这个方法的瓶颈在于其还是关心了数字之间的大小关系,而且没有考虑通过计数问题常用的组合数等方式去优化。
考虑上述dp方程的实际意义,其实就是求数列{ai}的组数,满足sigma(ai)=k且0<=ai<=i-1.
于是根据这个思路考虑优化的做法:
因为如果没有0<=ai<=i-1的限制答案就是一个组合数,
考虑利用容斥原理去干掉这个限制,
如果我们钦定至少有m个ai满足ai>=i,
设这些i的和为s, 则方案数为满足n个非负数和为(k-s)的方案数,
即为C(k-s+n-1,n-1),预处理后可以O(1)计算。
而由容斥原理可以发现,它对答案的贡献的系数是(-1)^m.
因为如果有p个不满足条件(p>0),
它会在sigma(C(p,2k))个位置做出1的贡献,
在sigma(C(p,2k+1))个位置做出-1的贡献,
在p>0时,其可以两两抵消,最终的贡献是0,
而在p=0时,其贡献为C(0,0)=1.
我们可以dp出选出m个i,和为s的方案数,然后组合数求解,
dp过程中,因为有dp[i][j]=dp[i][j-i]+dp[i-1][j-i]-dp[i-1][j-n-1],所以每个dp值都可以O(1)计算,
dp方程的解释:i个数,和为j-i的情况下,每个数加1可以形成i个数,和为j的状况,
但是,如果原来选出的数字中有n,是不合法的,所以减去,
同时,对于i个数和为j,有一个1被选择的情况没有考虑到,所以加上。
第一维的状态数是sqrt(k)的,所以可以O(k^1.5)求出最终的答案。
Code:
#include <bits/stdc++.h>#define ll long long#define mod 1000000007llusing namespace std;ll inv[200005],fac[200005];ll dp[100005],prv[100005];ll c[100005],p[100005];inline void pre(){int i;fac[0]=1ll;fac[1]=1ll;for (i=2;i<=200000;i++){fac[i]=fac[i-1]*((ll)(i))%mod;}inv[0]=1ll;inv[1]=1ll;for (i=2;i<=200000;i++){inv[i]=(mod-mod/i)*inv[mod%i]%mod;}for (i=2;i<=200000;i++){inv[i]=inv[i]*inv[i-1]%mod;}}inline ll cal(int n,int m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}int main (){int n,k,i,j;pre();scanf ("%d%d",&n,&k);for (i=0;i<=k;i++){c[i]=cal(i+n-1,n-1);p[i]=0;}dp[0]=1;p[k]=1;for (i=1;i<=450;i++){int tag=i&1;for (j=0;j<=k;j++) prv[j]=dp[j],dp[j]=0;for (j=i*(i+1)/2;j<=k;j++){dp[j]=dp[j-i]+prv[j-i];if (j-n-1>=0) {dp[j]-=prv[j-n-1];}while (dp[j]>=mod) {dp[j]-=mod;}if (dp[j]<0) {dp[j]+=mod;}if (!tag){p[k-j]+=dp[j];}else{p[k-j]-=dp[j];}}}ll ans=0;for (i=0;i<=k;i++){p[i]%=mod;if (p[i]<0) {p[i]+=mod;}ans+=(c[i]*p[i])%mod;if (ans>=mod) {ans-=mod;}}printf ("%lld\n",ans);return 0;}
- [Hackerrank 101 Hack 43&& MenciOJ P321] K-Inversion Permutations
- 【Hackerrank 101Hack 43】【JZOJ5135】K-Inversion Permutations 题解
- [JZOJ5135]逆序对/[HackerRank-101hack43]K-Inversion Permutations
- Hackerrank 101 Hack 42 Array Pairs
- [HackerRank 101 Hack 42]Array Pairs
- [HackerRank 101 Hack 51] Train Trip
- [HackerRank 101 Hack 51] Small Cubes
- [HackerRank 101 Hack 51] Testing the Game
- [hackerrank Value of all Permutations]
- [线段树][单调栈]HackerRank 101 Hack 50 .Boxes for Toys
- [线段树 || 主席树][Hash] HackerRank 101 Hack 49. Sorting Lists
- hackerRank
- HackerRank
- HackerRank
- HackerRank
- HackerRank
- HackerRank
- HackerRank
- Java基础入门
- 读书笔记(持续更新)
- 软件工程第八章知识点总结
- java实现excel表格上传和下载
- 手机控制urdf小车模型运动(二)-创建简单的机器人模型
- [Hackerrank 101 Hack 43&& MenciOJ P321] K-Inversion Permutations
- metasploitable2 中mutillidae(owasp10)报错数据库不存在的问题
- 【面试题】剑指offer11--求一个数的指数次方,模拟实现一个pow函数
- Linux查看CPU和内存使用情况
- WebView使用解析(二)之WebViewClient/WebChromeClient
- Kafka性能测试分析
- 两张二维人物图像互相换脸代码
- Kotlin开发之旅《二》—Kotlin的基本语法
- SQL Server