#include<iostream>
using namespace std;
int yearDay(int year)
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return 366;
}
return 365;
}
int main()
{
int time = 0;
for (int i = 1922; i <= 2020; ++i)
{
time += yearDay(i);
}
time -= 22;
cout << time * 24 * 60 << endl;
return 0;
}
3C:合并检测(填空10分_数学)
题目描述:
新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情, A 国准备给大量民众进病毒核酸检测。
然而,用于检测的试剂盒紧缺。为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人( k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k 个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k−1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用了 k+1 个试剂盒完成了 k 个人的检测。
`#include<iostream>
using namespace std;
int main()
{
int ans = 0;
int sum = 0x3f3f3f3f; // 初始化为一个很大的数,因为要求的是小于的情况
for (int i = 1; i <= 100; i++) // 枚举所有的检测数
{
if (100 % i == 0)
{
if (100 / i + i < sum)
{
sum = 100 / i + i;
ans = i; // 题目要求的是被分为多少组是最小的,所以需要进行记录
}
}
else
{
if (100 / i + 1 + i < sum)
{
sum = 100 / i + 1 + i;
ans = i; // 记录当前最小的检测数
}
}
}
cout << ans << endl;
return 0;
}`
4D:REPEAT程序(填空10分_模拟)
题目描述:
附件 prog.txt 中是一个用某种语言写的程序。
其中 REPEAT k 表示一个次数为 k 的循环。循环控制的范围由缩进表达,从次行开始连续的缩进比该行多的(前面的空白更长的)为循环包含的内容。
例如如下片段:
cpp复制代码
REPEAT 2:
A = A + 4
REPEAT 5:
REPEAT 6:
A = A + 5
A = A + 7
A = A + 8
A = A + 9
#include<iostream>
using namespace std;
int main()
{
int a = 0;
for (int i = 0; i < 2; i++) // 枚举所有的检测数
{
a += 4;
for (int j = 0; j < 5; ++j)
{
for (int k = 0; k < 6; ++k)
{
a += 5;
}
a += 7;
}
a += 8;
}
a += 9;
cout << a << endl; // 答案403
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
cin >> str;
int n = str.size();
for (int i = 0; i < n; ++i)
{
int n = (str[i] - '0');
if (n >= 0 && n <= 9)
{
for (int j = 0; j < n - 1; ++j) // 之前已经输出一个了
{
cout << str[i - 1];
}
}
else
{
cout << str[i];
}
}
return 0;
}
解析代码(二叉树的数组遍历)
cpp复制代码
#include<iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
long long arr[N];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> arr[i];
}
int maxv = -INF;
int depth = 1, res = 1;
for (int i = 1; i <= n; i *= 2)
{
long long s = 0; // 完全二叉树每层的开头为2^(n-1),结尾则是 2^n - 1
for (int j = i; j <= i * 2 - 1 && j <= n; j++) // j++就是同一层的下一个
{
s += arr[j];
}
if (s > maxv)
{
maxv = s;
res = depth;
}
depth++;
}
cout << res << endl;
return 0;
}
8H:走方格(编程题20分)
题目描述:
在平面上有一些二维的点阵。
这些点的编号就像二维数组的编号一样,从上到下依次为第 1 至第 n 行,从左到右依次为第 1 至第 m 列,每一个点可以用行号和列号来表示。
现在有个人站在第 1 行第 1 列,要走到第 n 行第 m 列。只能向右或者向下走。
注意,如果行号和列数都是偶数,不能走入这一格中。
问有多少种方案。
【输入格式】
输入一行包含两个整数 n, m。
【输出格式】
输出一个整数,表示答案。
【评测用例规模与约定】
对于所有评测用例,1≤n≤30,1≤m≤30。
解析代码(dp)
题目解析:简单的dp,dp [ i ] [ j ] 表示走到第 n 行第 m 列的方案数
cpp复制代码
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n = 0, m = 0;
cin >> n >> m;
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
// dp [ i ] [ j ] 表示走到第 n 行第 m 列的方案数
dp[0][1] = 1;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
if (i % 2 == 1 || j % 2 == 1)
{
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
cout << dp[n][m] << endl;
return 0;
}
9I:整数拼接(编程题25分)
题目描述:
样例输入
复制代码
4 2
1 2 3 4
样例输出
复制代码
6
【评测用例规模与约定】
对于 30% 的评测用例,1≤n≤1000,1≤K≤20,1≤Ai≤10^4。
对于所有评测用例,1≤n≤10^5,1≤K≤10^5,1≤Ai≤10^9。
解析代码1(暴力_超时)
**题目解析:**暴力模拟:(时间超限,过了0个民间测试用例。。。)
cpp复制代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int n = 0, k = 0;
cin >> n >> k;
vector<int> arr(n);
for (int i = 0; i < n; ++i)
{
cin >> arr[i];
}
int cnt = 0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (i == j)
continue;
string tmp1 = to_string(arr[i]);
string tmp2 = to_string(arr[j]);
string tmp = tmp1 + tmp2;
long long x = atoi(tmp.c_str());
if (x % k == 0)
++cnt;
}
}
cout << cnt << endl;
return 0;
}
解析代码2(数学+哈希)
根据题意可推出,A与B拼接可以推出等式 A + 10 ^ x + B ,题目可以翻译成是求A + 10 ^ x + B % K == 0的个数。
通过观察等式A + 10 ^ x ^ +B % K == 0进行等价变形,变成(A + 10 ^ x) % K = -B % K ,并且B与x正相关,则可以用一个哈希表存起来A + 10x,用空间换时间,那么我们的两重循环就可以换成一个只枚举A,调用哈希只需要O(1)的时间,到现在看来题目就迎刃而解了,此时时间复杂度为O(n)。补充: - B % K == (K - (B % K)) % K(感兴趣的话百度了解一下)
cpp复制代码
//#include<bits/stdc++.h>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
const int N = 100010;
typedef long long ll;
ll arr[N], hash_table[11][N];
int main()
{
int n = 0, k = 0;
cin >> n >> k;
for (int i = 0; i < n; ++i)
{
cin >> arr[i];
ll t = arr[i] % k;
for (int j = 0; j < 11; ++j)
{
hash_table[j][t]++;
t = t * 10 % k;
}
}
ll res = 0;
for (int i = 0; i < n; ++i)
{
int len = to_string(arr[i]).size();
res += hash_table[len][(k - (arr[i] % k)) % k];
ll t = arr[i] % k;
while (len--)
{
t = t * 10 % k;
}
if (t % k == (k - (arr[i] % k)) % k)
--res; //判重 如果查找到的值包括自己,减掉自己
}
cout << res << endl;
return 0;
}
//#include <bits/stdc++.h>
#include <iostream>
using namespace std;
const int N = 10010;
int w[N], p[N];
int Find(int x)
{
if (x != p[x])
p[x] = Find(p[x]);
return p[x];
}
void Union(int a, int b)
{
int x = Find(a);
int y = Find(b);
if (x != y) p[x] = y;
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
p[i] = i;
}
for (int i = 0; i < m; ++i)
{
int a, b, c;
cin >> a >> b >> c;
if (a == 1)
{
Union(b, c);
}
else
{
int x = Find(b);
for (int i = 1; i <= n; ++i)
{
if (x == Find(i))
w[i] += c;
}
}
}
for (int i = 1; i <= n; ++i)
{
cout << w[i] << " ";
}
return 0;
}
//#include <bits/stdc++.h>
#include <iostream>
using namespace std;
const int N = 10010;
int p[N], d[N];
int Find(int x)
{
if (p[x] == x || p[p[x]] == p[x])
return p[x];
int r = Find(p[x]);
d[x] += d[p[x]];
p[x] = r;
return r;
}
int main()
{
int n = 0, m = 0;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
p[i] = i;
}
while (m--)
{
int a, b, t;
cin >> t >> a >> b;
if (t == 1)
{
a = Find(a), b = Find(b);
if (a != b)
{
d[a] -= d[b]; //合并时,a结点的权值要减去b结点的权值
p[a] = b;
}
}
else
{
a = Find(a);
d[a] += b; // 直接往根结点上加权
}
}
for (int i = 1; i <= n; ++i)
{
if (Find(i) == i) // 如果是根结点,权值就为自己
printf("%d ", d[i]);
else // 如果不是根结点,权值需要加上根节点的值
printf("%d ", d[i] + d[Find(i)]);
}
return 0;
}