【xsy1143】 兔子的数字 搜索
题目大意:请找到第k大的数,满足各位数字之和等于各位数字之积。其中k≤1018。
首先我们要确定这个第k大的数有多大
我们用f[i][j][he][ji]表示我们要搜索一个i位的数字,还有j位没有确定,且确定的位总和为i,积为j的方案数。
我们发现:若he+j<ji,则f[i][j][he][ji]=0(假设后面大量地补1,即只增加各位数字之和而不增加各位数字之积,如果积过大,那么显然这种方法并不奏效)
若he+j=ji,则f[i][j][he][ji]=(ij)(这种情况下,余下的j位均为1恰好可以让和等于积,组合数的意义为将j个1插入到已经确定的i-j位数中)
若j=0,那么显然只需要判一下和是否等于积即可。
若在这三种情况外,直接枚举下一位数字(2到9枚举)。
我们设第k大的数字位数为x,每次计算f[x][x][0][1],若f[x][x][0][1]<n,则n−=f[x][x][0][1],并且x++,否则这个x即为第k大数的位数。
接着从大到小枚举每一位,随后计算当该数前若干位确定时的方案数,借此逐位确定整个数
时间复杂度为O(??)
1 #include<bits/stdc++.h> 2 #define L long long 3 #define M 505 4 using namespace std; 5 L n,c[M][M]={0}; 6 7 L calc(int n,int m,int he,int ji){ 8 if(he+m<ji) return 0; 9 if(!m) return he==ji; 10 if(he+m==ji&&ji!=1) 11 return c[n][m]; 12 L cnt=0; 13 for(int i=2;i<10;i++) 14 cnt+=calc(n,m-1,he+i,ji*i); 15 return cnt; 16 } 17 18 int main(){ 19 cin>>n; 20 for(int i=0;i<M;i++){ 21 c[i][0]=1; 22 for(int j=1;j<=i;j++) 23 c[i][j]=c[i-1][j]+c[i-1][j-1]; 24 } 25 if(n<10){printf("%d\n",n); return 0;} 26 n--; 27 int hh=1; 28 while(1){ 29 L now=calc(hh,hh,0,1); 30 if(now<n) n-=now,hh++; 31 else break; 32 } 33 int he=0,ji=1; 34 for(int i=hh;i;i--){ 35 for(int j=1;j<10;j++){ 36 L now=calc(i-1,i-1,he+j,ji*j); 37 if(now<n)n-=now; 38 else{ 39 printf("%d",j); 40 he+=j; ji*=j; 41 break; 42 } 43 } 44 } 45 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!