A:门派制作
答案:624
——————————————————————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int solve(int n){ int ans = 0; while(n > 0){ if(n % 10 == 2){ ans++; } n /= 10; } return ans; } int main(){ int ans = 0; for(int i = 1; i <= 2020; ++i){ ans += solve(i); } cout << ans << endl; return 0; }
|
B:既约分数
答案:2481215
——————————————————————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int gcd(int a, int b){ return b ? gcd(b, a%b) : a; } int main(){ int ans = 0; for(int i = 1; i <= 2020; ++i){ for(int j = 1; j <= 2020; ++j){ if(gcd(i, j) == 1){ ans++; } } } cout << ans << endl; return 0; }
|
C:蛇形填数
答案:761
分析
将脑袋向左歪45°再看看这个矩阵,把这个新的矩阵称为“斜矩阵”吧
1 2 6 7 15 16
3 5 8 14 17
4 9 13 18
10 12 19 25
11 20 24
21 23
22
斜着从上到下数的话,第i行共有i个数;
原矩阵的某k行k列,就是斜矩阵的第j行第j/2+1个数(j为奇数)
如[3][3] = 13
即第5行第3个数; [4][4] = 25
即第7行第4个数
那么k和j有什么关系呢,j = 2*k-1
于是[20][20]
就可以很愉快地得出是斜距阵的第39行第20个数
数是累加的,设斜距阵前38行共ans
个数,那么本题答案就是ans+20
再多看看就会发现,求前n行有多少个数,不就是等差数列前n项和吗?
于是ans + 20 = (1+38)*38/2 + 20 = 761
再多说一句都是废话了~
D:跑步锻炼
答案:8879
能用笔算的就不上代码,能上代码的就不要用excel
——————————————————————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| int months[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int main(){ int y = 2000, m = 1, d = 1; int ans = 0, week = 5; while(y != 2020 || m != 10 || d != 1){ if((y%4==0&&y%100!=0) || y%400==0){ months[2] = 29; }else{ months[2] = 28; } d++; if(d > months[m]){ d = 1; m++; } if(m == 13){ m = 1; y++; } week = (week+1) % 7; if(week == 0 || d == 1){ ans++; } ans++; } cout << ans+2 << endl; return 0; }
|
E:七段码
答案:80
分析
- 本题的思路其实来源于2016年蓝桥B组C++的
G题:剪邮票
一题
传送门:
- 将七段码看作七张牌,从中任选k张牌(k>1),然后判断k张牌是否相连,若相连,则满足题意
***注:为避免重复,选牌时排列不组合,共$\sum{C_{7}^{k}}(k = 1,2,…,7)$种可能的排列
——————————————————————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #include <iostream> #include <algorithm> #include <vector>
using namespace std;
int ans = 0; int b[8]; string s = "00000000"; int a[8][8]; vector<int> v; void line(int x, int y){ a[x][y] = 1; } void init(){ line(1, 2); line(2, 1); line(1, 3); line(3, 1); line(2, 4); line(4, 2); line(3, 4); line(4, 3); line(2, 5); line(5, 2); line(3, 6); line(6, 3); line(4, 5); line(5, 4); line(4, 6); line(6, 4); line(5, 7); line(7, 5); line(6, 7); line(7, 6); } void dfs_1(int x){ s[x] = '0'; for(int i = 1; i <= 7; ++i){ if(i == x){ continue; } if(s[i] == '1' && a[x][i] == 1){ dfs_1(i); } } } bool solve(){ s = "00000000"; for(int i = 0; i < v.size(); ++i){ s[v[i]] = '1'; } dfs_1(v[0]); if(s.find('1') == string::npos){ return true; }else{ return false; } } void dfs(int k, int step){ if(step >= 1){ if(solve()){ ans++; }
} for(int i = k; i <= 7; ++i){ if(!b[i]){ b[i] = 1; v.push_back(i); dfs(i, step+1); v.pop_back(); b[i] = 0; } } } int main(){ init(); dfs(1, 0); cout << ans << endl; return 0; }
|
F:成绩统计
题目来源:·【Acwing】·成绩统计
——————————————————————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| nt main(){ int n; double ans1 = 0, ans2 = 0; scanf("%d", &n); for(int i = 0; i < n; ++i){ int m; scanf("%d", &m); if(m >= 60){ ans1++; } if(m >= 85){ ans2++; } } printf("%.0lf%\n%.0lf%\n", ans1*100/n, ans2*100/n); return 0; }
|
G:回文日期
题目来源:·【Acwing】·回文日期
分析
- 直接从输入的日期n开始累加,上限即99991231
- 增加非法日期的判断,以及回文日期、ABABBABA型日期的判断即可
***注:建议不要用yy,mm,dd标记年月日,然后一天天累加,似乎这是取巧的办法,
这样虽然得到的都是合法日期,但后面可能涉及到string的拼接,这样效率反而变慢了,
笔者之前这样做的,亲测超时呦~
——————————————完整代码————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include <iostream> #include <algorithm> #include <sstream> using namespace std;
string ss1 = "0", ss2 = "0"; string judge1(string s){ for(int i = 0; i < s.length()/2; ++i){ if(s[i] != s[s.length()-1-i]){ return "0"; } } return s; } string judge2(string s){ if(judge1(s) == s && s[0] == s[2] && s[1] == s[3] && s[0] != s[1]){ return s; }else{ return "0"; } } string toString(int n){ stringstream ss; ss << n; return ss.str(); } int months[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; void solve(int n){ int y = n / 10000, m = n % 10000 / 100, d = n % 100; if((y%4==0&&y%100!=0) || y%400==0){ months[2] = 29; }else{ months[2] = 28; } if(m == 0 || m > 12 || d == 0 || d > 31 || months[m] < d){ return; } string s = toString(n); if(ss1 == "0") ss1 = judge1(s); if(ss2 == "0" && ss1 != "0") ss2 = judge2(s); } int main(){ int n; scanf("%d", &n); for(int i = n+1; i < 99991231; ++i){ solve(i); if(ss1 != "0" && ss2 != "0") break; } cout <<ss1 <<endl <<ss2 <<endl; return 0; }
|
H:子串分值和
题目来源:·【Acwing】·子串分值和
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1
分析
- 暴力的解法就不提了,观察发现,对于输入串s,每个s[i]真实统计的次数是有规律的
- 如s[0]真实统计的次数为
1*5
;s[2]真实统计的次数为2*3
;一句话概括就是
(s[i]当前位置到s[i]上一次出现的距离)*(s[i]到末端的距离)
***注:ACwing中的训练样例实在爆炸,结果只通过了一半数据。。。
——————————————完整代码————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <iostream> #include <algorithm>
typedef long long ll; using namespace std;
int word[26]; int main(){ string s; cin >> s; int n = s.length(); int a[n]; fill(word, word+26, -1); fill(a, a+n, -1); ll ans = 0; for(ll i = 0; i < n; ++i){ ans += (i - word[s[i]-'a']) * (n - i); word[s[i]-'a'] = i; } cout << ans << endl; return 0; }
|