BZOJ4714 : 旋转排列

对于每个$k$,问题等价于求有多少置换满足:

1.存在一个循环长度为$k$

2.任意一个循环长度$\geq 2$

枚举这种环的个数$t$:

设$g_t$表示至少有$kt$个人分成$t$个长度为$k$的循环的方案数,考虑枚举第一个人和哪些人分在了一起,同时有$(k-1)!$种可能的环,有$g_t=C(kt-1,k-1)g_{t-1}(k-1)!$。

设$d_i$表示$i$个人错位排列的方案数,那么至少有$t$个长度为$k$的循环的方案数为$C(n,kt)g_td_{n-kt}$。

考虑容斥,则这部分对答案的贡献为$(-1)^{t-1}C(n,kt)g_td_{n-kt}$。

时间复杂度$O(n\log n)$。

#include<cstdio>
const int N=500010,P=1000000007;
int n,i,j,k,t,f[N],inv[N],d[N],g[N],ans;
int main(){
  scanf("%d",&n);
  for(f[0]=i=1;i<=n;i++)f[i]=1LL*f[i-1]*i%P;
  for(inv[0]=inv[1]=1,i=2;i<=n;i++)inv[i]=1LL*(P-inv[P%i])*(P/i)%P;
  for(i=1;i<=n;i++)inv[i]=1LL*inv[i-1]*inv[i]%P;
  for(d[0]=d[2]=1,i=3;i<=n;i++)d[i]=1LL*(i-1)*(d[i-2]+d[i-1])%P;
  for(i=0;i<=n;i++)d[i]=1LL*d[i]*inv[i]%P;
  for(g[0]=1,i=2;i<=n;i++)for(j=1,k=i;k<=n;j++,k+=i){
    g[j]=1LL*g[j-1]*f[k-1]%P*inv[k-i]%P;
    t=1LL*inv[k]*d[n-k]%P*g[j]%P;
    if(j&1){
      ans+=t;
      if(ans>=P)ans-=P;
    }else{
      ans-=t;
      if(ans<0)ans+=P;
    }
  }
  ans=1LL*ans*f[n]%P;
  return printf("%d",ans),0;
}

  

时间: 2024-10-29 10:55:08

BZOJ4714 : 旋转排列的相关文章

记一道数字旋转排列算法题

记一道数字旋转排列算法题 面试的时候遇到一道算法题,当时没做出来,也没有什么思路.睡觉前突然想到解法,记录一下. 题的大意如下,数字以1开始,并围绕1做逆时针旋转,其中1的坐标为(0, 0),如下图所示: 要求给一个坐标,求其未知的数是多少?例:给出(1, 0),该坐标的数为2:给出(-1, -2),该坐标上的数为22. 说下解题思路,由点的坐标可以得出目标值所在的圈数p,比如5在第2圈,p的大小为坐标x或y较大绝对值n再+1,比如18为(-2,1),绝对值n为2,则18在第3圈(n+1),然后

第四章 颜色补充(硬件知识)

在颜色上,我一直存在着一些疑问,为什么显示器可以显示不同的颜色呢?越先进的浏览器显示颜色的机制更加复杂, 所以我在维基上搜索了一些关于最早的阴极射线管等知识,摘抄在下面.便于学习.这里对维基百科表示感谢. 荧幕尺寸依荧幕对角线计算,通常以英寸(inch)作为单位,现时一般主流尺寸有17".19".21".22".24.27"等,指荧幕对角的长度.常用的显示屏又有标屏(窄屏)与宽屏,方荧幕长宽比为4:3(还有少量比例为5:4),宽荧幕长宽比为16:10或16

新手算法学习之路----二分法Find Minimum in Rotated Sorted Array

题目:假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2). 你需要找到其中最小的元素. 你可以假设数组中不存在重复的元素. 思路:首先排除三种极端情况,空,只有一个元素,以及整个数组都是顺序排列的. 当顺序的数组随机旋转排列后,就分为两个顺序列入题目中的4567和012,寻找到中间数来和数组最后一个元素对比,如果大于的话说明最小的数在中间数的右边,如果小于的话说明最小数在中间数的左边,然             后继续按照二分法来找.

TPO1-48口语实用手册(文本词汇+短语)

TPO1 TASK 3 Administration  n. 管理部门 Acquire  v. 获得 Sculpture  n. 雕塑 Oppose  v. 反对 Financial  adj. 经济的 Tuition  n. 学费 Reserve  v. 保留保存 Steel plates n. 钢板 jutting out the earth 从地面上突出 odd  adj. 奇怪的 purchase  v. 购买购置 donor n. 捐赠者 anonymous adj. 匿名的 assu

用递归写排列组合问题

最近递归弄的人头疼,但是这两天看过来也稍微总结了一些不能称得上是技巧的技巧吧 问题如下,将1,2,3,4这四个数字排列组合的输出来,看网上有个很二的方法吧,就是将10000以内的数全部输出再筛选,对此有点无语,但是程序倒是挺好编的,嘿嘿 回归到正题中,用递归的思想解决 (1)采用旋转数字的方法,当步长为1时,1234还是1234,步长为2的时候,1234可以变为1243.1324...,步长为3 的时候,1234可以变为1423,诸如此类,最重要的能体现递归的就是将每次递归一次的数字还可以接着旋

CSS 实现加载动画之五-光盘旋转

原文:CSS 实现加载动画之五-光盘旋转 今天做的这个动画叫光盘旋转,名字自己取的.动画的效果估计很多人都很熟悉,就是微信朋友圈里的加载动画.做过前面几个动画,发现其实都一个原理,就是如何将动画的元素如何分离出来.这个动画的实现也很简单,关键点在于如何将元素拼凑成风车形状.然后定义动画的关键帧为rotate 360度,应用于整个元素上,就可以使整个元素旋转起来.案例在请在chrome中查看. 1. 先看截图 2. 代码实现思路 2.1 首先还是定义四个元素,元素的中心为这四个元素组成的圆的圆心.

CSS 实现加载动画之四-圆点旋转

原文:CSS 实现加载动画之四-圆点旋转 圆点旋转也是加载动画中经常用到的.其实现方式和菊花旋转一样,只不过一个是线条形式,一个是圆点形式.圆点按照固定的旋转角度排列,加上延时的改变透明度的动画就可以实现.这个实现也比较简单. 1. 动画截图 2. 案例源代码 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" Content="text/html

Josephus排列

思考与分析: 对于m为常数,可以用循环链表,用head,tail标志头尾指针使其易于表示循环结构.循环输出后删除结点n次,每次外层循环时,内层都固定循环m次.所以运行时间为O(mn)=O(n). 对于m为非常数.可以用顺序统计树,用size属性记录每个结点在当前树中所在的位置.经过一个取余过程,每次都能正确找到并输出删除每个结点,在经过n次循环,每次循环都要找到一个结点输出并删除它,所以每次循环都要花费O(lgn)时间.总的运行时间是O(nlgn). 代码如下: m为常数时: #include

【排列组合】

/* 排列组合 说明: 将一组数字.字母或符号进行排列,以得到不同的组合顺序,例如1 2 3这三个数的排列组合有:123.132.213. 231.312.321. 解法: 可以使用递回将问题切割为较小的单元进行排列组合,例如1234的排列可以分为1[234] .2[134] .3[124] .4[123]进行排列,这 边利用旋转法,先将旋转间隔设为0,将最右边的数字旋转至最左边,并逐步增加旋转的间隔, 例如: 1234->旋转1->继续将右边234进行递回处理 2134->旋转12为