标签:ota using ref lse put 今天 序列 字典序 desc
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 695 Accepted Submission(s): 254
#include<cstdio> #include<algorithm> using namespace std; int dis[10];//把n分解 int cnt,len,ans,k,n; bool lg1; int ws[10];//判断每一位都取值时最终的值是否可能超过n int dp[10];//取到底的记忆化 int les[10];//不取到底的记忆化(当前值已经大于n并且还没到底,就返回了) int dfs(int pos,int sum,int po){//sum*po为当前值,ws[pos]为上界, if(sum*po<ws[pos]&&dp[pos]!=-1&&(cnt+dp[pos]<k)){//当找的范围还在k内 cnt+=dp[pos];//当当前值小于上界时,就记忆化每一位都取的情况 return dp[pos]; } else if(sum*po>ws[pos]&&les[pos]!=-1&&(cnt+les[pos]<k)){ cnt+=les[pos];//当当前值大于上界,就记忆化至少有一位不选的情况(当至少有一位没取时可以保证 return les[pos];//最后得到的值一定小于n } int sum2=cnt; int sum1=0; if(sum<=n){//当当前值满足条件时 sum1++; cnt++; if(cnt==k){ ans=sum; lg1=false; return 0; } } else return 0; if(pos==0) return sum1; for(int i=0;i<=9&&lg1;i++){//往下走 sum1+=dfs(pos-1,sum*10+i,po/10); } //printf("%d %d\n",sum*po,ws[pos]); if(sum*po<ws[pos])//当没有到上界 dp[pos]=sum1; else if(sum*po>ws[pos])//当到上界 les[pos]=cnt-sum2; return sum1; } int main(){ int t; scanf("%d",&t); while(t--){ cnt=0; scanf("%d%d",&n,&k); len=0; fill(dp,dp+8,-1); fill(les,les+8,-1); int m=n; int po=1; while(m){ po*=10; dis[++len]=m%10; m/=10; } int r=1; int summ=0; for(int i=1;i<len;i++){ summ+=dis[i]*r; ws[i]=n-summ; r*=10; } lg1=true; for(int i=1;i<=9&&lg1;i++){ dfs(len-1,i,po/10); } printf("%d\n",ans); } return 0; }
标签:ota using ref lse put 今天 序列 字典序 desc
原文地址:https://www.cnblogs.com/cglongge/p/10852758.html