A题:空间
根据:
1MB = 1024KB
1KB = 1024B
1B = 8bit
由题可知
32bit = 4B
直接模拟即可
#include <iostream> using namespace std; int main () { cout << 256 * 1024 * 1024 / 4 <<endl; return 0; }
答案:67108864
B题:卡片
定义十个下标0-9的数组,每个数组包含数字2021,可表示为每个0-9的数字有2021个。
定义i=1表示为从1开始排数,取 i mod 10 的余数,对于每个余数a[i % 10] -- 即可,直到把某个数字减完。
1 #include <iostream> 2 using namespace std; 3 4 int main () 5 { 6 int a[10] = {2021,2021,2021,2021,2021,2021,2021,2021,2021,2021}; 7 8 int res = 0; 9 int i = 1; 10 while (i) 11 { 12 int k = i; 13 while (k) 14 { 15 if (a[k%10] == 0) 16 { 17 cout << res <<endl; 18 return 0; 19 } 20 a[k % 10] -- ; 21 k /= 10; 22 23 } 24 res++; 25 i ++; 26 } 27 28 return 0; 29 }
答案:3181
C题:直线
设直线方程y = kx + m;
根据直线性质:
斜率k = (y1 - y2) / (x1 - x2)
截距b = m
枚举每个点,这里需要注意的是,由于垂直线不存在斜率,所以当x1 = x2的时候不枚举。
定义Line结构体储存k,b。
在误差1e-8之内可算作同一条直线。
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 6 using namespace std; 7 8 const int N = 200000; 9 10 int n; 11 struct Line 12 { 13 double k, b; 14 bool operator< (const Line& t) const 15 { 16 if (k != t.k) return k < t.k; 17 return b < t.b; 18 } 19 }l[N]; 20 21 int main() 22 { 23 for (int x1 = 0; x1 < 20; x1 ++ ) 24 for (int y1 = 0; y1 < 21; y1 ++ ) 25 for (int x2 = 0; x2 < 20; x2 ++ ) 26 for (int y2 = 0; y2 < 21; y2 ++ ) 27 if (x1 != x2) 28 { 29 double k = (double)(y2 - y1) / (x2 - x1); 30 double b = y1 - k * x1; 31 l[n ++ ] = {k, b}; 32 } 33 34 sort(l, l + n); 35 int res = 1; 36 for (int i = 1; i < n; i ++ ) 37 if (fabs(l[i].k - l[i - 1].k) > 1e-8 || fabs(l[i].b - l[i - 1].b) > 1e-8) 38 res ++ ; 39 cout << res + 20 << endl; 40 41 return 0; 42 }
答案:40257
D题:货物摆放
用试除法枚举2021041820210418的每一个约数
直接遍历即可。
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 const int N = 1000010; 5 vector<long long> q; 6 7 int main () 8 { 9 int res = 0; 10 long long n = 2021041820210418; 11 12 for (long long i = 1 ; i * i <= n ; i ++ ) 13 { 14 if (n % i == 0) 15 { 16 q.push_back(i); 17 if (n / i != i ) q.push_back(n / i); 18 } 19 } 20 21 for (int a = 0 ; a < q.size() ; a++ ) 22 for (int b = 0 ; b < q.size() ; b ++ ) 23 for (int c = 0 ; c < q.size() ; c ++) 24 { 25 if (q[a] * q[b] * q[c] == n) 26 res++; 27 } 28 29 cout << res <<endl; 30 return 0; 31 }
答案:2430
F题:时间显示
题目只要求输出时分秒,所以可以先把N =/ 1000。
然后用N对一天之内的秒数取模,即 N %= 86400。
直接模拟即可。
#include <iostream> using namespace std; typedef long long LL; int main() { LL n; cin >> n; n /= 1000; n %= 86400; int h = n / 3600; n %= 3600; int m = n / 60; int s = n % 60; printf("%02d:%02d:%02d\n", h, m, s); return 0; }
H题:杨辉三角形
由于求的是数字第一次出现的位置,所以可以对杨辉三角轴对称切半,观察斜行。
不难发现除了第一斜行,每一斜行都是递增,因为C(n,m)n越大值越大,同理每一行也是递增。
根据杨辉三角性质可知:
1.每个数都会在杨辉三角的左半边出现
2.对于第n行第m个数字,其值为C(n-1,m-1)
3.在第35行18个时,C(34,17)> 109
上述可知,用二分可快速求出当前数第一次出现的次数。
1 #include <iostream> 2 using namespace std; 3 typedef long long ll; 4 5 int n; 6 7 ll bsearch(int a, int b) 8 { 9 ll res = 1; 10 for(int i = a, j = 1; j <= b; i--, j++) 11 { 12 res = res * i / j; 13 if(res > n) return res; 14 } 15 return res; 16 } 17 18 int check(int k) 19 { 20 ll l = 2 * k, r = n; 21 while(l < r) // 二分查找 22 { 23 int mid = l + r >> 1; 24 if(bsearch(mid, k) >= n) r = mid; 25 else l = mid + 1; 26 } 27 if(bsearch(r, k) != n) return 0; 28 cout << r * (r + 1) / 2 + k + 1 << endl; 29 return 1; 30 } 31 32 int main() 33 { 34 cin >> n; 35 36 for(int k = 16; ; k--) 37 if(check(k)) break; 38 return 0; 39 }