@description@

给定一个长度为 n 的序列 s1,s2,…,sn,它有 2^n−1 个非空子序列。请对于每个 k=0,1,2,…,n 统计 s 有多少非空子序列 a 经过重排成 b 后,ai = bi 的位置数量的最小可能值恰好为k。

input

第一行包含一个正整数 n ,表示序列的长度。

第二行包含 n 个正整数 s1,s2,…,sn,表示序列s。

output

输出 n+1 行,每行输出一个整数,第 i 行输出 k = i+1 的非空子序列数量。因为答案可能很大,请对 1000000007(=10^9+7) 取模输出。

sample input

5

2 3 2 5 5

sample output

18

11

2

0

0

0

对于 100% 的数据,1≤si≤n,n≤250000。

@solution@

不难观察发现,序列重排后与原位置相同的位置数最小可能值只与这个序列的众数有关。

(1)当 2*众数的出现次数 ≤ 序列长度 时,最小可能值为 0。

易证。具体操作方法是每次选择某个众数和其他的数交换。可以归纳验证该方法的可行性。

(2)否则,最小可能值 = 2*众数的出现次数 - 序列长度。

保留这些位置的数不动,然后就可以归纳到上面那一种情况。

枚举众数是哪个数。

因为情况(1)不好考虑,所以我们只考虑情况(2),用总数(2^n - 1)减去情况(2)的方案数就可以得到情况(1)的方案数。

考虑枚举出来的众数为 a,它的出现次数为 t,我们所选取的子序列长度为 l,其中包含 a 的个数为 x。

则:

\[ans[2*x - l] = \sum(C_{t}^{x}*C_{n-t}^{l-x})
\]

因为所有数的出现次数总和为 n,均摊下来是一个 O(n^2) 的算法。

标算使用的是卷积优化,但是模数实在有些恶心,所以我们机房的大佬想出来另一种算法爆踩标算:

先换元:令 d = 2*x - l,消去 l。可以得到:

\[ans[d] = \sum_t(\sum_xC_{t}^{x}*C_{n-t}^{x-d})
\]

由组合数的简单性质,可得:

\[ans[d] = \sum_t(\sum_xC_{t}^{t-x}*C_{n-t}^{x-d})
\]

考虑其组合意义,可以发现它等于:

\[ans[d] = \sum_t(C_{n}^{t-d})
\]

然后均摊 O(n),代码复杂度、时间复杂度、思维复杂度三重爆踩标算。

@accepted code@

  1. #include<cstdio>
  2. const int MOD = int(1E9) + 7;
  3. const int MAXN = 250000 + 5;
  4. inline int add(int x, int y) {return (x + y) % MOD;}
  5. inline int sub(int x, int y) {return add(x, MOD-y);}
  6. inline int mul(int x, int y) {return 1LL*x*y % MOD;}
  7. int pow_mod(int b, int p) {
  8. int res = 1;
  9. while( p ) {
  10. if( p & 1 ) res = mul(res, b);
  11. b = mul(b, b);
  12. p >>= 1;
  13. }
  14. return res;
  15. }
  16. int a[MAXN], cnt[MAXN], ans[MAXN], n;
  17. int fct[MAXN], inv[MAXN];
  18. void init() {
  19. fct[0] = 1;
  20. for(int i=1;i<=n;i++)
  21. fct[i] = mul(fct[i-1], i);
  22. inv[n] = pow_mod(fct[n], MOD - 2);
  23. for(int i=n-1;i>=0;i--)
  24. inv[i] = mul(inv[i+1], i + 1);
  25. }
  26. inline int comb(int n, int m) {
  27. if( n < m ) return 0;
  28. else return mul(fct[n], mul(inv[m], inv[n-m]));
  29. }
  30. int main() {
  31. scanf("%d", &n); init();
  32. for(int i=1;i<=n;i++) {
  33. int x; scanf("%d", &x);
  34. a[x]++;
  35. }
  36. for(int i=1;i<=n;i++)
  37. cnt[a[i]]++;
  38. ans[0] = sub(pow_mod(2, n), 1);
  39. for(int t=1;t<=n;t++)
  40. if( cnt[t] )
  41. for(int d=1;d<=t;d++)
  42. ans[d] = add(ans[d], mul(cnt[t], comb(n, t-d)));
  43. for(int i=1;i<=n;i++)
  44. ans[0] = sub(ans[0], ans[i]);
  45. for(int i=0;i<=n;i++)
  46. printf("%d\n", ans[i]);
  47. }

@details@

康复计划 - 2。

如果没有 zxb 与 typ 大佬的开导我可能真的要去写 拆系数fft/三模数ntt。

大佬您们太强了 orz。

顺便好像 typ 大佬是用的打表找到的规律,太强了我肯定看半天都看不出来规律 orz。

果然组合数学就是瞎搞公式2333

@noi.ac - 489@ shuffle的更多相关文章

  1. # NOI.AC省选赛 第五场T1 子集,与&最大值

    NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...

  2. NOI.ac #31 MST DP、哈希

    题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...

  3. NOI.AC NOIP模拟赛 第五场 游记

    NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...

  4. NOI.AC NOIP模拟赛 第六场 游记

    NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...

  5. NOI.AC NOIP模拟赛 第二场 补记

    NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...

  6. NOI.AC NOIP模拟赛 第一场 补记

    NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...

  7. NOI.AC NOIP模拟赛 第四场 补记

    NOI.AC NOIP模拟赛 第四场 补记 子图 题目大意: 一张\(n(n\le5\times10^5)\)个点,\(m(m\le5\times10^5)\)条边的无向图.删去第\(i\)条边需要\ ...

  8. NOI.AC NOIP模拟赛 第三场 补记

    NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...

  9. NOI.AC WC模拟赛

    4C(容斥) http://noi.ac/contest/56/problem/25 同时交换一行或一列对答案显然没有影响,于是将行列均从大到小排序,每次处理限制相同的一段行列(呈一个L形). 问题变 ...

随机推荐

  1. springboot中logback打印日志(转)

    springboot对logback的支持是非常好的,不需要任何配置,只需要在resource下加logback.xml就可以实现功能 直接贴代码: <?xml version="1. ...

  2. python基础--socket套接字、粘包问题

    本地回环地址:127.0.0.1 简易版服务端: import socket ​ server = socket.socket() # 就比如买了一个手机 server.bind(("127 ...

  3. P1561 [USACO12JAN]爬山Mountain Climbing

    P1561 [USACO12JAN]爬山Mountain Climbing 题目描述 Farmer John has discovered that his cows produce higher q ...

  4. R语言可视化二

    Lattice绘图系统 Lattice包: xyplot(散点图)/ bwplot / histrogram(柱状图)/ stripplot / dotplot(点图) 格式:xyplot(y~x | ...

  5. 阿里云MaxCompute 2019-7月刊

    您好,MaxCompute 2019.7月刊为您带来7月产品.技术最新动态,欢迎阅读. 导读 [发布]7月产品重要发布 [资讯]7月重要资讯 [文档]7月重要文档更新推荐 [干货]7月精选技术文章推荐 ...

  6. Data Lake Analytics IP白名单设置攻略

    当我们成功开通了 DLA 服务之后,第一个最想要做的事情就是登录 DLA 数据库.而登录数据库就需要一个连接串.下面这个页面是我们首次开通 DLA 之后的界面,在这里我们要创建一个服务访问点. 在上面 ...

  7. BZOJ 3296: [USACO2011 Open] Learning Languages

    Time Limit: 5 Sec Memory Limit: 128 MB Submit: 387 Solved: 206 [Submit][Status][Discuss] Description ...

  8. cmd操作oracle

    利用cmd的操作命令导出,详情如下(备注:方法二是转载网上的教程):1:G:\Oracle\product\10.1.0\Client_1\NETWORK\ADMIN目录下有个tnsname.ora文 ...

  9. vscode中编译输出c++是乱码

    vscode中编译输出c++是乱码的解决 环境说明:windows下面运行vscode win + R 右键属性 查看当前编码状态 知道当前环境的编码格式后,可以改变vscode上c++的格式 点击v ...

  10. 【JZOJ4743】【NOIP2016提高A组模拟9.2】积木

    题目描述 输入 输出 样例输入 3 8 7 6 3 9 4 1 10 5 输出 18 数据范围 样例解释 解法 容易从n<=15得出可以使用状态压缩动态规划. 设f[i][j][k]表示01状态 ...