zoukankan      html  css  js  c++  java
  • 【动态规划】51nod1780 完美序列

    巧妙的转化;f前两维大小开反TLE了一发……

    如果一个序列的相邻两项差的绝对值小于等于1,那么我们说这个序列是完美的。
    给出一个有序数列A,求有多少种完美序列排序后和数列A相同。

    Input

    第一行一个数n(<=30000)表示完美序列的长度
    第二行n个数,表示数列A(每个数<=10^9,每个数出现次数<=100)

    Output

    仅包含一个整数,表示可能的方案总数(对1,000,000,007取模)

    题目分析

    暑假讲过的题,今天第一眼还以为是什么玄妙计数……

    因为从左到右构造不现实,于是考虑将数字从小到大构造。这样的好处在于现在插入的$i$只和上一次$i-1$的状态有关系。

    $f[i][j][0/1][0/1]$表示处理到第$i$个数,第$i-1$个数两两间存空$j$个,左右两边分别是否有第$i-1$个数。转移的话就是用组合数统计,记得要预处理组合数。

    所以总时间复杂度$O(n*4*100)$.

     1 #include<bits/stdc++.h>
     2 const int MO = 1000000007;
     3 const int maxn = 30035;
     4 
     5 int f[maxn][103][3][3];
     6 int fac[103],C[103][103];
     7 int n,m,ans,a[maxn],t[maxn];
     8 
     9 int read()
    10 {
    11     char ch = getchar();
    12     int num = 0;
    13     for (; !isdigit(ch); ch=getchar());
    14     for (; isdigit(ch); ch=getchar())
    15         num = (num<<1)+(num<<3)+ch-48;
    16     return num;
    17 }
    18 int qmi(int a, int b)
    19 {
    20     int ret = 1;
    21     while (b)
    22     {
    23         if (b&1) ret = 1ll*ret*a%MO;
    24         a = 1ll*a*a%MO, b >>= 1;
    25     }
    26     return ret;
    27 }
    28 inline void Add(int &x, int y){x = (x+1ll*y)%MO;}
    29 int main()
    30 {
    31     n = read(), fac[0] = 1;
    32     for (int i=1; i<=n; i++) a[i] = read();
    33     for (int i=1; i<=100; i++) fac[i] = 1ll*fac[i-1]*i%MO;
    34     for (int i=0; i<=100; i++)
    35         for (int j=0; j<=i; j++)
    36             C[i][j] = 1ll*fac[i]*qmi(1ll*fac[j]*fac[i-j]%MO, MO-2)%MO;
    37     for (int i=1, j=1; i<=n; i++)
    38     {
    39         while (j<=n&&a[i]==a[j+1]) j++;
    40         if (a[i]+1 < a[j+1]){
    41             puts("0");
    42             return 0;
    43         }
    44         t[++m] = j-i+1, i = j;
    45     }
    46     f[1][t[1]-1][1][1] = 1;
    47     for (int i=1; i<m; i++)
    48         for (int j=0; j<t[i]; j++)
    49             for (int s1=0; s1<=1; s1++)
    50             for (int s2=0; s2<=1; s2++)
    51                 if (f[i][j][s1][s2])
    52                      for (int k=0; k<=j; k++)
    53                          for (int l1=0; l1<=s1; l1++)
    54                          for (int l2=0; l2<=s2; l2++)
    55                              if (k+l1+l2&&t[i+1] >= k+l1+l2)
    56                                 Add(f[i+1][t[i+1]-k-l1-l2][l1][l2], 1ll*f[i][j][s1][s2]*C[j][k]%MO*C[t[i+1]-1][k+l1+l2-1]%MO);
    57     for (int i=0; i<=100; i++)
    58         for (int j=0; j<=1; j++)
    59             for (int k=0; k<=1; k++)
    60                 Add(ans, f[m][i][j][k]);
    61     printf("%d
    ",ans);
    62     return 0;
    63 }

    END

  • 相关阅读:
    键盘记录器,可截获到 QQ 的password
    《python源代码剖析》笔记 pythonm内存管理机制
    Unity 捕获IronPython脚本错误
    POJ 3020 Antenna Placement 最大匹配
    XCL-Charts画线图(Line Chart)
    android设置背景色为透明
    设计时属性文件
    Windows Mobile基础
    Wince 的CAB安装包
    惠普的 ipaq112 恢复出厂设置
  • 原文地址:https://www.cnblogs.com/antiquality/p/9822939.html
Copyright © 2011-2022 走看看