FZU 1074 數位dp+二分
阿新 • • 發佈:2019-02-16
給m,n,問含有m個0的第k個數,是幾位數,最高位是多少
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <string> #include <cmath> using namespace std; #define inf 0x3f3f3f3f #define PI acos(-1.0) typedef __int64 ll; const int maxn=30; ll dp[maxn][maxn][maxn],k,m,a[30]; ll dfs(int pos,int num,bool limit,bool lead) { if(pos==-1) { if(lead) return 0; return num==m; } if(!limit&&!lead&&dp[pos][num][m]!=-1) return dp[pos][num][m]; int up=limit?a[pos]:9; ll ans=0; for(int i=0;i<=up;i++) { if(lead) ans+=dfs(pos-1,num,limit&&a[pos]==i,lead&&i==0); else { if(i==0) ans+=dfs(pos-1,num+1,limit&&a[pos]==i,lead&&i==0); else ans+=dfs(pos-1,num,limit&&a[pos]==i,lead&&i==0); } } if(!limit&&!lead) dp[pos][num][m]=ans; return ans; } ll solve(ll x) { if(x<0) return 0; int pos=0; while(x) { a[pos++]=x%10; x/=10; } return dfs(pos-1,0,true,true); } int main() { int t; scanf("%d",&t); memset(dp,-1,sizeof(dp)); ll ans=0; while(t--) { // cin >> m >> k; scanf("%I64d%I64d",&m,&k); ll l=1,r=9e18,mid; while(l<r-1) { mid=(r+l)/2; if(solve(mid)>=k) r=mid; else l=mid; } ll len=(ll)log10(r*1.0)+1; l=len-1; ll s=1; while(l--) s*=10; printf("%I64d %I64d\n",len,r/s); } return 0; }