http://codeforces.com/contest/111/problem/D

Little Petya loves counting. He wants to count the number of ways to paint a rectangular checkered board of size n × m (n rows, m columns) in k colors. Besides, the coloring should have the following property: for any vertical line that passes along the grid lines and divides the board in two non-empty parts the number of distinct colors in both these parts should be the same. Help Petya to count these colorings.

Input

The first line contains space-separated integers n, m and k (1 ≤ n, m ≤ 1000, 1 ≤ k ≤ 106) — the board's vertical and horizontal sizes and the number of colors respectively.

Output

Print the answer to the problem. As the answer can be quite a large number, you should print it modulo 109 + 7 (1000000007).

Examples
Input
  1. 2 2 1
Output
  1. 1
Input
  1. 2 2 2
Output
  1. 8
Input
  1. 3 2 2
Output
  1. 40
  2.  
  3. 题意:
    给出一个 n*m 的矩阵,用sum种颜色染色
    满足:任意一条竖直线(纵线)把矩阵划分成的2个部分,2个部分的不同的颜色数相同
    求方案数
    n,m <= 10^3,sum <= 10^6
  4.  
  5. solution:
    注意到n,m的范围不大
  6.  
  7. 显然有以下性质:
    1.1列和第m列的颜色数一定相等
    2.2m-1列的颜色只能从1m列的颜色的交集中选择
  8.  
  9. m=1的时候,特殊处理,ans=k^n
    m>1的时候,我们只需要考虑1m列的颜色选择还有交集大小
  10.  
  11. 预处理g[i]表示恰好用i种颜色涂满n个格子的方案数
    (此时n是一个常量)
  12.  
  13. 如果用递推式,求g[i]需要O(n^2),求g数组需要O(n^3),tle
    考虑二项式反演求g数组:
    h(i)表示用i种颜色染n个格子的方案数,则h(i) = i^n
    g(i)表示恰好用i种颜色染n个格子的方案数,
    有:h(y) = sigma(i=0,i<=y)(C(y,i)*g(i))
    则:g(y) = sigma(i=0,i<=y)((-1)^(y-i) * C(y,i) * h(i))
         = sigma(i=0,i<=y)((-1)^(y-i) * C(y,i) * i^n)
  14.  
  15. 这样求g[i]需要O(nlogn),求g数组需要O(n^2*logn)
    当然也可以优化到O(n^2)求g数组
  16.  
  17. 主要的预处理部分搞定了,然后就是答案了
    退下公式,得到:
    ans = sigma(j=0,j<=min(n,sum))C(sum,j) * j^(m*n-2*n) *
        (sigma(i=0,i<=min(n-j,(sum-j)/2))(C(sum-j,i)*C(sum-j-i,i)*g(i+j)^2))
  1. //File Name: cf111D.cpp
  2. //Author: long
  3. //Mail: 736726758@qq.com
  4. //Created Time: 2016年05月16日 星期一 01时13分24秒
  5.  
  6. #include <stdio.h>
  7. #include <algorithm>
  8. #include <iostream>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12.  
  13. #define LL long long
  14.  
  15. using namespace std;
  16.  
  17. const int MAXN = + ;
  18. const int MAXM = + ;
  19. const int MOD = (int)1e9 + ;
  20.  
  21. LL jie[MAXM];
  22. LL g[MAXN];
  23.  
  24. LL qp(LL x,LL y){
  25. LL res = ;
  26. while(y){
  27. if(y & ) res = res * x % MOD;
  28. x = x * x % MOD;
  29. y >>= ;
  30. }
  31. return res;
  32. }
  33.  
  34. LL get_c(LL x,LL y){
  35. if(x < y) return ;
  36. if(x == y || y == ) return ;
  37. return jie[x] * qp(jie[y] * jie[x - y] % MOD,MOD - ) % MOD;
  38. }
  39.  
  40. void init(int sum,int n){
  41. jie[] = ;
  42. for(int i=;i<MAXM;i++)
  43. jie[i] = jie[i-] * i % MOD;
  44. int ma = min(sum,n);
  45. LL now;
  46. for(int i=;i<=ma;i++){
  47. for(int k=;k<=i;k++){
  48. now = get_c(i,k) * qp(k,n) % MOD;
  49. if((i - k) % )
  50. g[i] = (g[i] - now + MOD) % MOD;
  51. else
  52. g[i] = (g[i] + now) % MOD;
  53. }
  54. }
  55. }
  56.  
  57. LL solve(int n,int m,int sum){
  58. if(m == ) return qp(sum,n);
  59. init(sum,n);
  60. LL ans = ,now,tmp;
  61. int ma = min(sum,n);
  62. for(int j=,ma2;j<=ma;j++){
  63. now = ;
  64. ma2 = min(n - j,(sum - j) / );
  65. for(int i=;i<=ma2;i++){
  66. (now += jie[sum-j] * qp(jie[sum-j-*i]*jie[i]%MOD*jie[i]%MOD,MOD - ) % MOD
  67. * g[i+j] % MOD * g[i+j] % MOD) %= MOD;
  68. }
  69. tmp = qp(j,(m - ) * n) % MOD;
  70. (ans += get_c(sum,j) * tmp % MOD * now % MOD) %= MOD;
  71. //cout << j << " " <<ans << endl;
  72. }
  73. return ans;
  74. }
  75.  
  76. int main(){
  77. int n,m,k;
  78. scanf("%d %d %d",&n,&m,&k);
  79. printf("%d\n",(int)solve(n,m,k));
  80. return ;
  81. }
  1.  

cf111D Petya and Coloring 组合数学,二项式反演的更多相关文章

  1. 洛谷 P5400 - [CTS2019]随机立方体(组合数学+二项式反演)

    洛谷题面传送门 二项式反演好题. 首先看到"恰好 \(k\) 个极大值点",我们可以套路地想到二项式反演,具体来说我们记 \(f_i\) 为钦定 \(i\) 个点为极大值点的方案数 ...

  2. [LOJ3119][CTS2019|CTSC2019]随机立方体:组合数学+二项式反演

    分析 感觉这道题的计数方法好厉害.. 一个直观的思路是,把题目转化为求至少有\(k\)个极大的数的概率. 考虑这样一个事实,如果钦定\((1,1,1),(2,2,2),...,(k,k,k)\)是那\ ...

  3. codeforces111D. Petya and Coloring(组合数学,计数问题)

    传送门: 解题思路: 要求一条直线分割矩阵时左右颜色数一样,那么就说明一个问题.直线左右移动时是不会改变左右矩阵的颜色集合的.所以说明:2~m-1列的颜色集一定属于第一列与第m列颜色集的交集.而且第一 ...

  4. UVAlive-7040 color(组合数学,二项式反演)

    链接:vjudge 题目大意:有一排方格共 $n$ 个,现在有 $m$ 种颜色,要给这些方格染色,要求相邻两个格子的颜色不能相同.现在问恰好用了 $k$ 种颜色的合法方案数.答案对 $10^9+7$ ...

  5. [模板] 容斥原理: 二项式反演 / Stirling 反演 / min-max 容斥 / 子集反演 / 莫比乌斯反演

    //待更qwq 反演原理 二项式反演 若 \[g_i=\sum_{j=1}^i {\binom ij} f_j\] , 则有 \[ f_i=\sum_{j=1}^i (-1)^{i-j} {i \ch ...

  6. P4859 已经没有什么好害怕的了(dp+二项式反演)

    P4859 已经没有什么好害怕的了 啥是二项式反演(转) 如果你看不太懂二项式反演(比如我) 那么只需要记住:对于某两个$g(i),f(i)$ ---------------------------- ...

  7. 【LOJ#6374】网格(二项式反演,容斥)

    [LOJ#6374]网格(二项式反演,容斥) 题面 LOJ 要从\((0,0)\)走到\((T_x,T_y)\),每次走的都是一个向量\((x,y)\),要求\(0\le x\le M_x,0\le ...

  8. 2018.11.07 hdu1465不容易系列之一(二项式反演)

    传送门 其实标签只是搞笑的. 没那么难. 二项式反演只是杀鸡用牛刀而已. 这道题也只是让你n≤20n\le20n≤20的错排数而已. 还记得那个O(n)O(n)O(n)的递推式吗? 没错那个方法比我今 ...

  9. 洛谷4859 BZOJ3622 已经没什么好害怕的了(DP,二项式反演)

    题目链接: 洛谷 BZOJ 题目大意:有两个长为 $n$ 的序列 $a,b$,问有多少种重排 $b$ 的方式,使得满足 $a_i>b_i$ 的 $i$ 的个数比满足 $a_i<b_i$ 的 ...

随机推荐

  1. Linux软件安装管理概述

    介绍如何在Linux字符界面下安装软件 课程大纲: 一.软件包管理简介 二.rpm命令管理 三.yum在线管理 四.源码包管理 五.脚本安装包

  2. layer 一款口碑极佳的web弹层组件,弹框专用

    研究学习网址: http://layer.layui.com/

  3. Android Studio + gradle多渠道打包

    通过工具栏的Build->Build Apk 好像只能打包第一个Module(eclipse里面是Project的概念),怎么多渠道打包呢?目前好像只能一个一个的打 首先在清单文件里设置个变量: ...

  4. connect to tomcat with JMX

    Answering my own question; turned out to be easier than i thought. Following needs to be done, for e ...

  5. 使用substring和split方法从字符串中抽取一组清单

    提取前: '这是一个句子.这是一个句子,包含了一列清单: 樱桃, 橙子, 桔子, 苹果, 香蕉.这是清单内容.'; 提取后: ["樱桃", " 橙子", &qu ...

  6. Linux实时监控工具Nmon使用

    官网:http://nmon.sourceforge.net/pmwiki.php?n=Main.HomePage 下载:http://sourceforge.net/projects/nmon/fi ...

  7. 检测php网站是否已经被攻破

    from :http://www.gregfreeman.org/2013/how-to-tell-if-your-php-site-has-been-compromised/ http://drop ...

  8. shell之函数

    function 所有函数在使用前必须定义.这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用.调用函数仅使用其函数名即可.可以将函数看作是脚本中的一段代码,但是有一个主 ...

  9. unity, 保存prefab时material丢失问题

    在程序运行时用replacePrefab(gameObj,prefab)或createPrefab(gameObj,prefab)保存prefab,遇到保存出来的prefab中material丢失的问 ...

  10. OpenJudge计算概论-循环移动

    /*=============================================================================== 循环移动 总时间限制: 1000ms ...