6 条题解
-
8
100分做法
楼下打表是真的不至于
#include<bits/stdc++.h> using namespace std; short t; int ans,x; // ans用来计算答案,x用来计算最高位的那个数字 string n,e,nulll; // 这里n用字符串记比较方便后面的计算,e用来计算一个判断字符串,nulll存储一个空字符串,方便e归零(但不是真的变成'0') int main(){ cin>>t; for(short i=1;i<=t;i++){ ans=0; cin>>n; int len=n.length(); ans+=(len-1)*9; /* 找规律可以发现: 1≤n≤9(个位)时,最多ans为9(9*1) 10≤n≤99(十位)时,最多ans为18(9*2) 100≤n≤999(百位)时,最多ans为27(9*3) ··· 也就是说ans至少为(它的位数-1)*9 */ x=n[0]-'0'; // 计算最高位的那个数字 ans+=x-1; // 最高位为x,观察上面的规律可以发现答案还包括(最高位-1)个 /* 比如:34567 按照ans+=(len-1)*9得到ans已经为36 很明显,11111 22222 33333 也是特殊数字 一共有3个(x个) 但是如果数字是32569,则一共有x-1个 所以保险起见这里先加上x-1个,最后一个数字在后面判断 */ e=nulll; // 字符串e归零。 for(int j=0;j<len;j++){ // 创造出一个每一位都一样的特殊数字 e+=n[0]; /* 继续按上面34567的例子说 当数字最高位是3并且一共有5位时,创建的数字就会是5位的3···3 也就是33333 */ } if(n>=e)++ans; /* 然后由于'0'~'9'是按照字典序排列的,所以直接按字典序比较n和e的大小就行了 比较出来如果n>=e(34567≥33333)就说明还包括e(33333) ans最后再+1就行了 */ cout<<ans<<"\n"; } return 0; }
精简无注释版
#include<bits/stdc++.h> using namespace std; short t; int ans,x; string n,e,nulll; int main(){ cin>>t; for(short i=1;i<=t;i++){ ans=0; cin>>n; int len=n.length(); ans+=(len-1)*9; x=n[0]-'0'; ans+=x-1; e=nulll; for(int j=0;j<len;j++){ e+=n[0]; } if(n>=e)++ans; cout<<ans<<"\n"; } return 0; }
-
1
《暴力做法》
#include<bits/stdc++.h> using namespace std; int t; string n; bool f(string a) { int c=a.length(); for(int i=1;i<c;i++) { if(a[0]>a[i]) { return 1; } if(a[i]>a[0]) { break; } } return 0; }
别想抄哦!
int main() { cin>>t; for(int i=1;i<=t;i++) { cin>>n; cout<<n[0]-'0'-f(n)+9*(n.length()-1)<<endl; } return 0; }
-
1
😄 如果按照题目叙述遍历是不行的,因为1~n之间的数字都需要逐个判断,而n的范围是,字符串做法也无从谈起,所以只能反向构造,刚开始我是这么写的:
if (n > 1000000000) // 是一个10位数 { cnt = 81; for (int i = 1111111111; i <= n; i += 1111111111) { cnt ++; } } else if (n > 100000000) // 是一个9位数 { cnt = 72; for (int i = 111111111; i <= n; i += 111111111) { cnt ++; } }
没错的啦,从大往小写,写到最后就能看出有没有写错~就是这样,不要忘记给cnt清0:
else // 是一个1位数 { for (int i = 1; i <= n; i += 1) { cnt ++; } } cout << cnt << endl; cnt = 0;
这样的话可以AC,但是本质上还是枚举,算不得构造,可以找到一些规律,然后用数组的特性来构造,9个为一轮,本轮的数依靠上一轮的数得出:
n 1 2 3 4 5 6 7 8 9 特殊数字的个数 1 2 3 4 5 6 7 8 9 n 11 22 33 44 55 66 77 88 99 特殊数字的个数 10 11 12 13 14 15 16 17 18 n 111 222 333 444 555 666 777 888 999 特殊数字的个数 19 20 21 22 23 24 25 26 27 n 1111 2222 3333 4444 5555 6666 7777 8888 9999 特殊数字的个数 28 29 30 31 32 33 34 35 36 以特殊数字出现的个数作为数组下标,可以找到构造方法,注意定义一个p专门递增下标,不要和轮数的循环变量i以及每轮内部递增的循环变量j混起来,这很重要:
for (int i = 1; i <= 9; i++) { a[++p] = i; } for (int i = 0; i < 9; i++) { for (int j = 1; j <= 9; j++) { a[++p] = a[i * 9 + j] * 10 + j; } }
然后就可以看看输入的n落在了哪个值内,来找数组下标,也即特殊数字出现的次数
while (t--) { cin >> n; for (int i = 1; i <= 100; i++) { if (a[i] > n) { cout << i - 1 << endl; break; } } }
因为n最大为,所以i不会超过81,给100够够的了。
-
-2
刚看到这道题的时候有点难受,划到最下面发现数据好大啊,要是像往常那样%10再/10我估计会超时,所以,
让我们快乐的打表吧但是这个表可不能乱打,有些太久的打表方法肯定不能用,不然要等好久所以,不知道大家发现了没有,对于1-9来说,+1就可以让ans+1,而11-110中,加11就可以让ans+1,111-1110以及后面则以此类推,但10要特判,输出9,ans在打表时也要手动改,下面是AC打表代码。#include <bits/stdc++.h> using namespace std; long long t,ans; bool flag=true; long long n; int main(){ cin>>t; while(t--){ cin>>n; ans=0; if(n<10)ans=n; if(n==10)ans=9; if(n>=11&& n<22)ans=10; if(n>=22&& n<33)ans=11; if(n>=33&& n<44)ans=12; if(n>=44&& n<55)ans=13; if(n>=55&& n<66)ans=14; if(n>=66&& n<77)ans=15; if(n>=77&& n<88)ans=16; if(n>=88&& n<99)ans=17; if(n>=99&& n<110)ans=18; if(n>=111&& n<222)ans=19; if(n>=222&& n<333)ans=20; if(n>=333&& n<444)ans=21; if(n>=444&& n<555)ans=22; if(n>=555&& n<666)ans=23; if(n>=666&& n<777)ans=24; if(n>=777&& n<888)ans=25; if(n>=888&& n<999)ans=26; if(n>=999&& n<1110)ans=27; if(n>=1111&& n<2222)ans=28; if(n>=2222&& n<3333)ans=29; if(n>=3333&& n<4444)ans=30; if(n>=4444&& n<5555)ans=31; if(n>=5555&& n<6666)ans=32; if(n>=6666&& n<7777)ans=33; if(n>=7777&& n<8888)ans=34; if(n>=8888&& n<9999)ans=35; if(n>=9999&& n<11110)ans=36; if(n>=11111&& n<22222)ans=37; if(n>=22222&& n<33333)ans=38; if(n>=33333&& n<44444)ans=39; if(n>=44444&& n<55555)ans=40; if(n>=55555&& n<66666)ans=41; if(n>=66666&& n<77777)ans=42; if(n>=77777&& n<88888)ans=43; if(n>=88888&& n<99999)ans=44; if(n>=99999&& n<111110)ans=45; if(n>=111111&& n<222222)ans=46; if(n>=222222&& n<333333)ans=47; if(n>=333333&& n<444444)ans=48; if(n>=444444&& n<555555)ans=49; if(n>=555555&& n<666666)ans=50; if(n>=666666&& n<777777)ans=51; if(n>=777777&& n<888888)ans=52; if(n>=888888&& n<999999)ans=53; if(n>=999999&& n<1111110)ans=54; if(n>=1111111&& n<2222222)ans=55; if(n>=2222222&& n<3333333)ans=56; if(n>=3333333&& n<4444444)ans=57; if(n>=4444444&& n<5555555)ans=58; if(n>=5555555&& n<6666666)ans=59; if(n>=6666666&& n<7777777)ans=60; if(n>=7777777&& n<8888888)ans=61; if(n>=8888888&& n<9999999)ans=62; if(n>=9999999&& n<11111110)ans=63; if(n>=11111111&& n<22222222)ans=64; if(n>=22222222&& n<33333333)ans=65; if(n>=33333333&& n<44444444)ans=66; if(n>=44444444&& n<55555555)ans=67; if(n>=55555555&& n<66666666)ans=68; if(n>=66666666&& n<77777777)ans=69; if(n>=77777777&& n<88888888)ans=70; if(n>=88888888&& n<99999999)ans=71; if(n>=99999999&& n<111111110)ans=72; if(n>=111111111&& n<222222222)ans=73; if(n>=222222222&& n<333333333)ans=74; if(n>=333333333&& n<444444444)ans=75; if(n>=444444444&& n<555555555)ans=76; if(n>=555555555&& n<666666666)ans=77; if(n>=666666666&& n<777777777)ans=78; if(n>=777777777&& n<888888888)ans=79; if(n>=888888888&& n<999999999)ans=80; if(n>=999999999&& n<1111111110)ans=81; cout<<ans<<endl; } return 0; }
这个打表呢是不知道怎么优化才这样做的,但是如果有更优解法的话望各位dalao指教
-
-6
写题解请注意 鼓励大家写题解,但注意题解格式。
题解一定要有思路解析或代码注释,能否让别人理解你的思路
也是你的能力的检验,不要只放无意义的代码给大家复制,那就失去了做题的初心。
给代码两端加上这个会舒服一些
```cpp
你的代码
```
</span>
这个点在键盘的左上角tab上面那个键,注意切换输入法
#include<iostream> using namespace std; int main() { int n; cin>>n;//这是一个注释 return 0; }
请注意严禁抄袭题解,写题解不要只放代码,需加上你的思路或代码注释。
抄袭题解一经发现直接取消成绩。
题解被删除的可能
- 代码不符合格式规范
- 没有思路讲解或者没有注释,
- 无意义的题解
大家携手共同维护一个良好的编程环境,如果一经发现,多次作乱。可能会被管理员拉黑,请注意,一旦拉黑即失去登陆资格。
- 1
信息
- ID
- 1275
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 206
- 已通过
- 86
- 上传者