题目链接:https://vjudge.net/contest/254142#problem/G
参考题解:https://blog.csdn.net/zearot/article/details/47984379
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define LL __int128 5 #define ull unsigned long long 6 #define mst(a,b) memset((a),(b),sizeof(a)) 7 #define mp(a,b) make_pair(a,b) 8 #define pi acos(-1) 9 #define pii pair<int,int> 10 #define pb push_back 11 const int INF = 0x3f3f3f3f; 12 const double eps = 1e-6; 13 const int MAXN = 1e5 + 10; 14 const int MAXM = 2e6 + 10; 15 const ll mod = 1e9 + 7; 16 17 int f[15][100], dig[15]; 18 19 void init() { 20 mst(f, 0); 21 f[0][0] = 1; 22 for(int i = 1; i <= 10; i++) 23 for(int j = 0; j <= i * 9; j++) 24 for(int k = 0; k <= min(9, j); k++) 25 f[i][j] += f[i - 1][j - k]; 26 } 27 28 int findall(int pos,int sum,bool limit) { 29 if(!limit || !pos) return f[pos][sum]; 30 int ans = 0, mx = min(dig[pos], sum); 31 for(int i = 0; i <= mx; i++) 32 ans += findall(pos - 1,sum - i,limit && i == dig[pos]); 33 return ans; 34 } 35 36 int shu[15]; 37 38 void findd(int pos,int sum,int rnk,bool limit) { 39 if(!pos) return ; 40 if(!limit) { 41 int mx = min(9, sum); 42 for(int i = 0; i <= mx; i++) { 43 if(f[pos - 1][sum - i] < rnk) rnk -= f[pos - 1][sum - i]; 44 else { 45 shu[pos] = i; 46 findd(pos - 1,sum - i,rnk,limit); 47 return ; 48 } 49 } 50 } else { 51 int mx = min(dig[pos], sum); 52 for(int i = 0; i <= mx; i++) { 53 int temp = findall(pos - 1,sum - i,i == dig[pos]); 54 if(temp < rnk) rnk -= temp; 55 else { 56 shu[pos] = i; 57 findd(pos - 1,sum - i,rnk,i == dig[pos]); 58 return ; 59 } 60 } 61 } 62 } 63 64 int main() 65 { 66 #ifdef local 67 freopen("data.txt", "r", stdin); 68 // freopen("data.txt", "w", stdout); 69 #endif 70 init(); 71 int n,len = 0; 72 scanf("%d",&n); 73 while(n) { 74 dig[++len] = n % 10; 75 n /= 10; 76 } 77 int ans = 0,sum = 0; 78 for(int i = 1; i <= len * 9; i++) { 79 int num = findall(len,i,true); 80 if(!num) continue; 81 int l = 1, r = num, num1; 82 bool flag = false; 83 while(l <= r) { 84 int mid = (l + r) >> 1; 85 findd(len,i,mid,true); 86 num1 = 0; 87 for(int j = len; j >= 1; j--) { 88 if(!num1 && !shu[j]) continue; 89 num1 = num1 * 10 + shu[j]; 90 } 91 if(sum + mid > num1) l = mid + 1; 92 else if(sum + mid < num1) r = mid - 1; 93 else { 94 flag = true; 95 break; 96 } 97 } 98 if(flag) ans++; 99 sum += num; 100 } 101 printf("%d\n",ans); 102 return 0; 103 }
原文地址:https://www.cnblogs.com/scaulok/p/9683006.html
时间: 2024-10-22 10:49:33