[HAOI2010]计数
II.[HAOI2010]计数
我不得不吐槽出题人的语文实在太……那个了。
翻译一下:给你一个数,求它是全排列中第几个。
为什么呢?我们看一下给定的那个的例子。显然,在任何合法的数中,所有的非零数的出现次数,在每个数中都是相同的。如果我们允许前导零,那么所有的的出现次数也都相同了。(删去可以看作将移到了开头)
我们考虑借鉴数位DP的思想:从高位向低位枚举,并考虑当前这位填入比原数小的数还是和原数相同的数。
如果填入一个比它小的数,那么后面的位就可以全排列了。
考虑每个数共出现了次,所有数总共出现了次。
数字可以在这个位置里面随便填,共种方案。
数字可以在剩下个位置里面随便填,共种方案。
以此类推。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,num[100],cnt[10],C[100][100],res;
char s[100];
int calc(int tot){
int ans=1;
for(int i=0;i<10;i++)ans*=C[tot][cnt[i]],tot-=cnt[i];
return ans;
}
signed main(){
scanf("%s",s+1),n=strlen(s+1);
for(int i=0;i<=n;i++)C[i][0]=1;
for(int i=1;i<=n;i++)for(int j=1;j<=i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];
// for(int i=0;i<=n;i++){for(int j=0;j<=i;j++)printf("%d ",C[i][j]);puts("");}
for(int i=1;i<=n;i++)num[i]=s[i]-'0',cnt[num[i]]++;
for(int i=1;i<=n;i++){
for(int j=0;j<num[i];j++){
if(!cnt[j])continue;
cnt[j]--;
res+=calc(n-i);
cnt[j]++;
}
cnt[num[i]]--;
}
printf("%lld\n",res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?