题目链接:https://atcoder.jp/contests/abc154/tasks/abc154_e
题目大意
给定一个整数N($1 \leq N \leq 10^{100}$)和K($1 \leq K \leq 3$),求[1, N]区间内数位上只有K个非零数的整数个数。
分析
找一下规律即可,详情见代码注释。
代码如下
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 /*-------------------Define Start-------------------*/ 5 typedef bool BL; // 布尔类型 6 typedef char SB; // 有符号1字节,8位 7 typedef unsigned char UB; // 无符号1字节,8位 8 typedef short SW; // 有符号短整型,16位 9 typedef unsigned short UW; // 无符号短整型,16位 10 typedef long SDW; // 有符号整型,32位 11 typedef unsigned long UDW; // 无符号整型,32位 12 typedef long long SLL; // 有符号长整型,64位 13 typedef unsigned long long ULL; // 无符号长整型,64位 14 typedef char CH; // 单个字符 15 typedef float R32; // 单精度浮点数 16 typedef double R64; // 双精度浮点数 17 18 #define Rep(i, n) for (register SDW i = 0; i < (n); ++i) 19 #define For(i, s, t) for (register SDW i = (s); i <= (t); ++i) 20 #define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i) 21 #define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) 22 #define ms0(a) memset(a,0,sizeof(a)) 23 #define msI(a) memset(a,0x7f,sizeof(a)) 24 #define LOWBIT(x) ((x)&(-x)) 25 26 #define MP make_pair 27 #define PB push_back 28 #define ft first 29 #define sd second 30 31 #define pr(x) cout << #x << " = " << x << " " 32 #define prln(x) cout << #x << " = " << x << endl 33 34 const ULL mod = 1e9 + 7; //常用模数(可根据题目需要修改) 35 const ULL inf = 0x7fffffff; //用来表示无限大 36 const ULL infLL = 0x7fffffffffffffffLL; //用来表示无限大 37 /*-------------------Define End-------------------*/ 38 39 const UDW maxN = 1e6 + 7; 40 string N; 41 SLL len; 42 SDW K; 43 SLL ans; 44 45 void input(){ 46 cin >> N >> K; 47 len = N.size(); 48 } 49 50 void do1() { 51 SDW a = N[0] - ‘0‘; 52 SLL posA = len; // 从1开始从右往左数a在第几个 53 54 // 1 ~ len - 1位数的情况 55 ans += 9 * (posA - 1); 56 // len位数的情况 57 ans += a; 58 } 59 60 void do2() { 61 SDW a = N[0] - ‘0‘; 62 SLL posA = len; // 从1开始从右往左数a在第几个 63 64 SDW b = 0; // b为从左往右数第二个非零的数,不存在就置为0,然后位置设为1 65 SLL posB = 1; 66 67 For(i, 1, len - 1) { 68 if(N[i] != ‘0‘) { 69 b = N[i] - ‘0‘; 70 posB = len - i; 71 break; 72 } 73 } 74 75 // 1 ~ len - 1位数的情况 76 ans += 9 * (posA - 1) * (posA - 2) * 9 / 2; 77 // len位数的情况 78 ans += (a - 1) * (posA - 1) * 9; // posA上置 1 ~ a-1 79 ans += (posB - 1) * 9; // posA上置 a, posB上置 0 80 ans += b; // posA上置 a, posB上置 1 ~ b 81 } 82 83 void do3() { 84 SDW a = N[0] - ‘0‘; 85 SLL posA = len; // 从1开始从右往左数a在第几个 86 87 SDW b = 0; // b为从左往右数第二个非零的数,不存在就置为0,然后位置设为1 88 SLL posB = 1; 89 90 For(i, 1, len - 1) { 91 if(N[i] != ‘0‘) { 92 b = N[i] - ‘0‘; 93 posB = len - i; 94 break; 95 } 96 } 97 98 SDW c = 0; // c为从左往右数第三个非零的数,不存在就置为0,然后位置设为1 99 SLL posC = 1; 100 101 For(i, len - posB + 1, len - 1) { 102 if(N[i] != ‘0‘) { 103 c = N[i] - ‘0‘; 104 posC = len - i; 105 break; 106 } 107 } 108 109 // 1 ~ len - 1位数的情况 (朱世杰恒等式) 110 ans += 9 * 9 * 9 * (posA - 1) * (posA - 2) * (posA - 3) / 6; 111 // len位数的情况 112 ans += (a - 1) * 9 * 9 * (posA - 1) * (posA - 2) / 2; // posA上置 1 ~ a-1 113 ans += 9 * 9 * (posB - 1) * (posB - 2) / 2; // posA上置a, posB上置 0 114 ans += (b - 1) * (posB - 1) * 9; // posA上置a, posB上置 1 ~ b-1 115 ans += (posC - 1) * 9; // posA上置a, posB上置 b, posC上置0 116 ans += c; // posA上置a, posB上置 b, posC上置1~c 117 } 118 119 void solve(){ 120 switch(K) { 121 case 1:{ 122 do1(); 123 break; 124 } 125 case 2:{ 126 do2(); 127 break; 128 } 129 case 3:{ 130 do3(); 131 break; 132 } 133 default:{ 134 assert(false); 135 } 136 } 137 } 138 139 void output(){ 140 cout << ans << endl; 141 } 142 143 int main() { 144 input(); 145 solve(); 146 output(); 147 return 0; 148 }
原文地址:https://www.cnblogs.com/zaq19970105/p/12298255.html
时间: 2024-10-08 11:07:11