CS Academy #32 G
2024-08-29 01:36:24
题意:
分析:
考虑如何求方案数
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)解决了
#include<bits/stdc++.h>
using namespace std;
const int maxn=,mod=1e9+;
int dp[maxn+][maxn+];
int n,k,m;
int ans=;
void inc(int &a,int b)
{
a=(a+b)%mod;
}
int Pow(long long a,int b)
{
long long ans=;
while(b)
{
if(b&) ans=ans*a%mod;
a=a*a%mod;
b>>=;
}
return ans;
}
int main()
{ scanf("%d%d%d",&n,&k,&m);
dp[][]=;
for(int i=;i<=k;++i)
for(int j=;j<=n;++j)
{
if(j>=)
inc(dp[i][j],dp[i-][j-]);
if(j>=i-)
inc(dp[i][j],dp[i][j-i]);
}
for(int i=;i<=n;++i)
{
int s=;
for(int j=;j<=k&&i*j<=n;++j)
inc(s,dp[k-j][n-i*j]);
inc(ans,1LL*s*Pow(1LL*i,m)%mod);
}
printf("%d\n",ans);
return ;
}
最新文章
- 数据结构 B-树和B+树的应用:数据搜索和数据库索引
- CentOS7 增加tomcat 启动,停止,使用systemctl进行配置
- java 21 - 7 IO流小结的图解
- C开发基础--函数调用栈
- bodyParser注意“需要请求头的支持”
- 台电幻彩u盘拆解
- Hibernate API申明事务边界
- HTML的盒子模型
- 在C#中使用GDAL创建Shape文件
- C++ 类中的引用成员变量初始化
- header 头各种类型文件下载
- git用代码库文件完全覆盖本地/git不能提交jar的设置
- Learning Structured Representation for Text Classification via Reinforcement Learning 学习笔记
- ubuntu 使用旧式Gnome风格的菜单
- ecna2017-Game of Throwns
- windows10安装ubuntu16.04双系统
- win10安装OpenSSL及简单的使用
- c++静态变量与菲静态变量
- 安装vmware虚拟机和linux(centos)
- matlab 基本操作
热门文章
- PAT (Basic Level) Practise (中文)-1029. 旧键盘(20)
- 【JavaScript】两种常见JS面向对象写法
- How To:Linux下如何通过命令检查网卡是否插上网线
- Luogu P4231 三步必杀 (差分)
- redis集群理解
- ajax实现上传图片保存到后台并读取
- S3C6410串口平台设备注册流程分析
- ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze
- EFCore CodeFirst模型迁移生成数据库备注(mysql)
- [android开发篇]elicpse安装教程