zoukankan      html  css  js  c++  java
  • CCPC2020 秦皇岛 H Holy Sequence

    题意:

    $a_1……a_n$ 满足要求当且仅当 $1<=a_i<=n$,且 $max(a_{1},……,a_{i})-max(a_{1},……,a_{i-1})<=1$。

    现在问长度为n的所有满足条件的序列里面,数字 $i$ 出现次数的平方的和,$n<=3000$,模数现给。

    题解:

    妙啊。

    首先,$x^2$可以理解为有$x$个元素,从这$x$个元素中可重复的有次序的选出两个数的方案数。

    那么我们可以把选择方案分成以下几个情况:

    1、选择数字 $i $第一次出现的位置和之后出现的某个位置

    2、选择数字 $i $第二次出现或之后的两个位置

    3、选择数字 $i $第一次出现的位置两次

    4、选择数字 $i$ 第二次或之后的一个位置选择两次

    这道题有一个很有趣的性质,就是第 $i$ 位往后的方案数与 $1$~$i$ 的最大值有直接关系,所以我们可以先枚举 数字 i 第一次出现的位置,然后算出以 i 打头,往后一定长度的方案数,数字 i 第一次出现的位置为 j  的方案数,然后根据组合数算出最终答案。

    首先,我们先算数字 i 第一次出现的位置为 j 的方案数,设 $f [ i ] [ j ]$  为数字$i$ 第一次出现的值为 j 的方案数。不难发现答案就是斯特林数,因为数据小,直接递推即可。

    之后,我们去算以 i 打头,之后长度为 j 且序列合法的方案数 ,设 $H [ i ] [ j ]$为以 $j$ 打头,之后长度为 $i-1$ 且序列合法的方案数 。

    一开始我想转移方程是

    $H [ i ] [ j ] = sum_{k=1}^{j+1}H [i-1] [k]$

    但是这样是不正确的。因为 $H[i-1][1……j+1]$在前 $i-1$次的转移中的上限并不是 $j$ ,所以正确的转移应当是

    $H [ i ] [ j ] = H [ i-1 ] [ j ] * j+ H [ i-1 ] [ j+1 ] $

    这样转移本质上就是让 $H [ i-1 ] [ j ]$接在第2位上,第一位填 $j$ ,且第2位从 $j$改成 $1$~ $j$ 的总方案。

    现在,让我们考虑第 1 种情况如何转移。

    首先,我们可以利用$f[i-1][j-1]$枚举出来数字 $j $第一次出现在哪个位置,之后,我们可以利用组合数,在剩下的$n-i$个位置中调出一个代表我们选了在这个位置的$j$,然后剩下的位置的方案数用H[n-i][j]和组合数进行计算。

    第2中情况也是这样

    我们还是利用$f[i-1][j-1]$枚举数字j第一次出现的位置,之后在$n-i$个位置中挑出两个位置为$j$,剩下的位置的方案数用$H[n-i-1][j]$和组合数进行计算。

    第3、4中情况同理

    值得注意的是,$(x,y)和(y,x)$算两种选择方案,所以第1、2种情况要乘以2。

     1 #include<cstdlib>
     2 #include<cstdio>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #define N 3005
     8 using namespace std;
     9 int T,n,p;
    10 int F[N][N],G[N][N];
    11 long long ans[N];
    12 long long ksm(long long x,long long z)
    13 {
    14     long long ans=1;
    15     while(z)
    16     {
    17         if(z&1)
    18         {
    19             ans=ans*x%p;
    20         }
    21         x=x*x%p;
    22         z>>=1;
    23     }
    24     return ans;
    25 }
    26 long long C[N][N];
    27 int main()
    28 {
    29     scanf("%d",&T);
    30     int cnt=0;
    31 
    32     while(T--)
    33     {
    34         cnt++;
    35         scanf("%d%d",&n,&p);
    36         memset(ans,0,sizeof(ans));
    37         C[0][0]=1;
    38         for(int i=1;i<=n;i++)
    39         {
    40             C[i][0]=1;
    41             for(int j=1;j<=2;j++) C[i][j]=C[i-1][j]+C[i-1][j-1],C[i][j]%=p;
    42         }
    43         F[1][1]=1;
    44         F[0][0]=1;
    45         for(int i=1;i<=n;i++)
    46         {
    47             for(int j=1;j<=i;j++)
    48             {
    49                 F[i][j]=(1ll*F[i-1][j]*j%p+F[i-1][j-1])%p;
    50             }
    51         }
    52         for(int i=n;i;i--) G[1][i]=1;
    53         for(int i=2;i<=n;i++)
    54         {
    55             for(int j=1;j<=n;j++)
    56             {
    57                 G[i][j]=(1ll*G[i-1][j]*j%p+G[i-1][j+1])%p;
    58             }
    59         }
    60         for(int i=1;i<=n;i++) 
    61         {
    62             int tmp1=0,tmp2=0;
    63             for(int j=1;j<=i;j++)
    64             {    
    65                 if(n-i-1>0) tmp1=(1ll*G[n-i-1][j]*j+G[n-i-1][j+1])%p;
    66                 else if(n-i-1==0) tmp1=1;
    67                 if(n-i-2>0) tmp2=(1ll*G[n-i-2][j]*j+G[n-i-2][j+1])%p;
    68                 else if(n-i-2==0) tmp2=1;
    69                 ans[j]=(1ll*ans[j]+3ll*F[i-1][j-1]%p*tmp1%p*C[n-i][1]%p)%p;
    70                 ans[j]=(1ll*ans[j]+2ll*F[i-1][j-1]%p*tmp2%p*C[n-i][2]%p);
    71                 ans[j]=(1ll*ans[j]+1ll*F[i-1][j-1]*G[n-i+1][j]%p)%p;
    72             }
    73         }
    74         printf("Case #%d:
    ",cnt);
    75         for(int i=1;i<n;i++)
    76         {
    77             printf("%d ",ans[i]);
    78         }
    79         printf("%d",ans[n]);
    80         printf("
    ");
    81         
    82     }
    83     return 0;
    84 }
    View Code
  • 相关阅读:
    案例19-页面使用ajax显示类别菜单
    案例18-首页最新商品和热门商品显示
    案例17-validate自定义校验规则校验验证码是否输入正确
    案例16-validate自定义校验规则校验用户名是否存在
    案例15-基本的表单校验使用validate
    测开之路六十九:监控平台之视图层
    测开之路六十八:监控平台之监控逻辑和处理逻辑
    测开之路六十七:监控平台之附加功能准备
    测开之路六十六:UI测试平台之处理逻辑和蓝图添加到程序入口
    测开之路六十五:UI测试平台之js
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13872622.html
Copyright © 2011-2022 走看看