SGU 492 经典数位dp

来源:互联网 发布:软件性能测试分类 编辑:程序博客网 时间:2024/05/17 06:02

计数时不要某个数字,求数字对应的序号或者求某个序号对应的数字

解决方式是记忆化搜索

long long 是肯定的,并注意n最大时对应的答案的范围

原来1000000000000000000 < pow(2.0,62)……


#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <vector>using namespace std;#define ll  long longll dp[2][20];int num[20];ll dfs(int cur,bool ok,int pre) // ok is no limit or not,pre is 1 previous or not{if(ok && dp[pre][cur]!=-1)return dp[pre][cur];if(cur==0)return 1;ll ret=0;for(int i=0;i<10;++i){if(!ok && i>num[cur])break;if(pre && i==3)continue;if(!ok && i==num[cur])ret+=dfs(cur-1,false,i==1?1:0);elseret+=dfs(cur-1,true,i==1?1:0);}if(ok)return dp[pre][cur]=ret;else return ret;}int main (){int test;scanf("%d",&test);memset(dp,-1,sizeof(dp));while(test--){ll n;cin>>n;int cnt=0;ll left=0,right=2000000000000000000;while(left<right){ll mid=(left+right)/2;ll k=mid;int cnt=0;while(k){num[++cnt]=k%10;k/=10;}ll res=dfs(cnt,false,0);res--;if(res>=n)right=mid;else left=mid+1;}cout<<left<<endl;}return 0;}


原创粉丝点击