zoukankan      html  css  js  c++  java
  • CS Academy #32 G

    题意:

      

    分析:

      考虑如何求方案数

      dp[i][j]表示i个数字的和为j的方案数,这是个经典问题,转移有两种,一个是填一个数字1,一个是整体加1

      然后这个问题并不是求方案数,而是求对应的权值和

      我们很容易想到dp[i][j]维护对应的m个下降幂Σx^i,最后再用斯特林数还原成m次幂

      但这样时间复杂度是O(nmk)的,无法接受

      题解给出了一个很妙的想法,我们去计算每个数字对答案的贡献,我们只关心这个数字出现的次数,不妨设我们现在考虑数字x

      x出现总次数={x恰好出现一次的方案数}*1+{x恰好出现两次的方案数}*2+......

      这样无法求解

      但可以转换成这样:

      x出现总次数={x至少出现一次的方案数}+{x至少出现两次的方案数}+.......

            =dp[k-1][n-x]+dp[k-2][n-2x]+dp[k-3][n-3x]+.......

      这样就可以O(nk)解决了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=4096,mod=1e9+7;
     4 int dp[maxn+5][maxn+5];
     5 int n,k,m;
     6 int ans=0;
     7 void inc(int &a,int b)
     8 {
     9     a=(a+b)%mod;
    10 }
    11 int Pow(long long a,int b)
    12 {
    13     long long ans=1;
    14     while(b)
    15     {
    16         if(b&1) ans=ans*a%mod;
    17         a=a*a%mod;
    18         b>>=1;
    19     }
    20     return ans;
    21 }
    22 int main()
    23 {    scanf("%d%d%d",&n,&k,&m);
    24     dp[0][0]=1;
    25     for(int i=1;i<=k;++i)
    26         for(int j=1;j<=n;++j)
    27         {
    28             if(j>=1)
    29             inc(dp[i][j],dp[i-1][j-1]);
    30             if(j>=i-1)
    31             inc(dp[i][j],dp[i][j-i]);
    32         }
    33     for(int i=1;i<=n;++i)
    34     {
    35         int s=0;
    36         for(int j=1;j<=k&&i*j<=n;++j)
    37             inc(s,dp[k-j][n-i*j]);
    38         inc(ans,1LL*s*Pow(1LL*i,m)%mod);
    39     }
    40     printf("%d
    ",ans);
    41     return 0;
    42 }
    View Code
  • 相关阅读:
    sql 自定义函数-16进制转10进制
    编写一个单独的Web Service for Delphi
    Web Service
    无需WEB服务器的WEBServices
    Svn总是提示输入账号密码
    阿里云服务器SQLSERVER 2019 远程服务器环境搭建
    svn客户端使用
    数据库设计规则(重新整理)
    数据库表字段命名规范
    怎样去掉DELPHI 10.3.3 启动后的 security alert 提示窗体
  • 原文地址:https://www.cnblogs.com/wmrv587/p/8638408.html
Copyright © 2011-2022 走看看