汪汪汪,不如第一场麻 😄 ,day2
🤗题目列表
A、求余(5分)
#include<iostream>
using namespace std;
int main()
{
cout<<2021%20<<endl;
return 0;
}
// 1
B、双阶乘(5分)
这里硬算,必爆,所以我们每次乘都要取余
1 x 3 x 5 x 7 ... x 2021 % MOD // 由乘法和取模的性质,我们可以边乘边取模
#include<iostream>
using namespace std;
int main()
{
int res = 1;
for(int i = 1 ; i <= 2021 ; i += 2)
res = res * i % 100000;
cout<<res<<endl;
return 0;
}
// 59375
C、格点(10分)
👴没仔细看题嗷,x和y从0开始枚举了,考试这样必寄
#include<iostream>
using namespace std;
int main()
{
int res = 0;
for(int x = 1 ; x <= 2021 ; x++)
for(int y = 1 ; y <= 2021 ; y++)
if(x * y <= 2021)
res++;
cout<<res<<endl;
return 0;
}
// 15698
D、整数分解(10分)
非常简单只要
#include<iostream>
using namespace std;
int main()
{
long long res = 0;
for(int i = 1 ; i <= 2021 ; i++)
for(int j = 1 ; j <= 2021 - i ; j++)
for(int k = 1 ; k <= 2021 - i - j ; k++)
for(int l = 1 ; l <= 2021 - i - j - k ; l++)
for(int m = 1 ; m <= 2021 - i - j - k - l ; m++)
if(i + j + k + l + m == 2021)
res++;
cout<<res<<endl;
return 0;
}
哈哈哈,开玩笑的,我跑了3分钟都没跑出来
这题用隔板法
所以这题就转化为求 C 2020 4 C_{2020}^{4} C20204
#include<iostream>
using namespace std;
int main()
{
long long res = 1;
for(int i = 2020 ,j = 1 ; j <= 4 ; i--,j++)
res = res * i / j;
cout<<res<<endl;
return 0;
}
// 691677274345
E、城邦(15分)
最小生成树,y总写的Kruskal,不说了,今天复习图论了,早该忘忘了
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2030, M = N * N / 2;
int n = 2021, m;
int p[N];
struct Edge
{
int a, b, c;
bool operator< (const Edge& t) const
{
return c < t.c;
}
}e[M];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int get(int x, int y)
{
int res = 0;
while (x || y)
{
int a = x % 10, b = y % 10;
if (a != b) res += a + b;
x /= 10, y /= 10;
}
return res;
}
int main()
{
for (int i = 1; i <= n; i ++ ) p[i] = i;
for (int i = 1; i <= n; i ++ )
for (int j = i + 1; j <= n; j ++ )
e[m ++ ] = {i, j, get(i, j)};
sort(e, e + m);
int res = 0;
for (int i = 0; i < m; i ++ )
{
int a = e[i].a, b = e[i].b, c = e[i].c;
if (find(a) != find(b))
{
res += c;
p[find(a)] = find(b);
}
}
cout<<res<<endl;
return 0;
}
// 4046
F、特殊年份(15分)
今年是 2021 年,2021 这个数字非常特殊,它的千位和十位相等,个位比百位大 1,我们称满足这样条件的年份为特殊年份。
输入 5 个年份,请计算这里面有多少个特殊年份。
输入格式
输入 5 行,每行一个 4 位十进制数(数值范围为 1000 至 9999),表示一个年份。
输出格式
输出一个整数,表示输入的 5 个年份中有多少个特殊年份。
输入样例:
2019
2021
1920
2120
9899
输出样例:
2
样例解释
2021 和 9899 是特殊年份,其它不是特殊年份。
嗯造就完事了,语法题,y总直接用字符串来读然后来比较,那样做更简单
#include<iostream>
using namespace std;
int main()
{
int m = 5;
int res = 0;
while(m--)
{
int year;
cin>>year;
int a = year / 1000,b = year % 1000 / 100,
c = year % 100 / 10,d = year % 10;
if(a == c && d - 1 == b)
res ++;
}
cout<<res<<endl;
return 0;
}
G、小平方(20分)
小蓝发现,对于一个正整数 n和一个小于 n 的正整数 v,将 v 平方后对 n 取余可能小于 n 的一半,也可能大于等于 n的一半。
请问,在 1 到 n−1中,有多少个数平方后除以 n 的余数小于 n 的一半。
例如,当 n=4 时,1,2,3 的平方除以4的余数都小于 4 的一半。
又如,当 n=5 时,1,4的平方除以 5 的余数都是 1,小于 5 的一半。
而 2,3 的平方除以 5 的余数都是 4,大于等于 5的一半。
输入格式
输入一行包含一个整数 n。
输出格式
输出一个整数,表示满足条件的数的数量。
数据范围
1≤n≤1000
输入样例:
5
输出样例:
2
把 < 看成 <= 加油(ง •_•)ง
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int res = 0;
for(int i = 1 ;i < n ; i++)
if(i * i % n * 2 < n ) // 防止取整问题
res ++;
cout<<res<<endl;
return 0;
}
H、完全平方数(20分)
一个整数 a 是一个完全平方数,是指它是某一个整数的平方,即存在一个整数 b,使得 a = b 2 a = b^2 a=b2。
给定一个正整数 n,请找到最小的正整数 x,使得它们的乘积是一个完全平方数。
输入格式
输入一行包含一个正整数 n。
输出格式
输出找到的最小的正整数 x。
数据范围
对于 30% 的评测用例,1≤n≤1000,答案不超过 1000。
对于 60% 的评测用例,1≤n≤
1
0
8
10^8
108,答案不超过
1
0
8
10^8
108。
对于所有评测用例,1≤n≤
1
0
12
10^{12}
1012,答案不超过
1
0
12
10^{12}
1012。
输入样例1:
12
输出样例1:
3
输入样例2:
15
输出样例2:
15
分解质因数,嗨呀,数论也忘了不少捏🤗
如果 n ∗ x = m 2 n * x = m ^ 2 n∗x=m2 ,就可以得出结论,m的任何一个质因子的次数都是偶数,只有是偶数,质因子才能分成2份,所以这题就是,给我们一个n,让我们求n至少乘上多少,使得n里面,每个质因子的次数变成偶数
#include<iostream>
using namespace std;
typedef long long LL;
int main()
{
LL n;
cin>>n;
LL res = 1;
for(LL i = 2 ; i * i <= n ; i++)
if(n % i == 0)
{
int s = 0;
while(n % i == 0) s++,n /= i;
if(s % 2) res *= i;
}
if(n > 1) res *= n;
cout<<res<<endl;
return 0;
}
I、负载均衡(25分)
有 n台计算机,第 i 台计算机的运算能力为 v i v_i vi。
有一系列的任务被指派到各个计算机上,第 i 个任务在 a i a_i ai 时刻分配,指定计算机编号为 b i b_i bi,耗时为 c i c_i ci 且算力消耗为 d i d_i di。
如果此任务成功分配,将立刻开始运行,期间持续占用 b i b_i bi 号计算机 d i d_i di 的算力,持续 c i c_i ci 秒。
对于每次任务分配,如果计算机剩余的运算能力不足则输出 −1,并取消这次分配,否则输出分配完这个任务后这台计算机的剩余运算能力。
输入格式
输入的第一行包含两个整数 n,m 分别表示计算机数目和要分配的任务数。
第二行包含 n 个整数 v1,v2,⋅⋅⋅ v n v_n vn,分别表示每个计算机的运算能力。
接下来 m 行每行 4 个整数 a i a_i ai, b i b_i bi, c i c_i ci, d i d_i di,意义如上所述。数据保证 a i a_i ai 严格递增,即 a i < a i + 1 a_i<a_{i+1} ai<ai+1。
输出格式
输出 m 行,每行包含一个数,对应每次任务分配的结果。
数据范围
对于 20% 的评测用例,n,m≤200。
对于 40% 的评测用例,n,m≤2000。
对于所有评测用例,1≤n,m≤200000,1≤
a
i
a_i
ai,
c
i
c_i
ci,
d
i
d_i
di,
v
i
v_i
vi≤
1
0
9
10^9
109,1≤
b
i
b_i
bi≤n
输入样例:
2 6
5 5
1 1 5 3
2 2 2 6
3 1 2 3
4 1 6 1
5 1 3 3
6 1 3 4
输出样例:
2
-1
-1
1
-1
0
样例解释
时刻 1,第 1 个任务被分配到第 1 台计算机,耗时为 5,这个任务时刻 6 会结束,占用计算机 1 的算力 3。
时刻 2,第 2 个任务需要的算力不足,所以分配失败了。
时刻 3,第 1 个计算机仍然正在计算第 1 个任务,剩余算力不足 3,所以失败。
时刻 4,第 1 个计算机仍然正在计算第 1 个任务,但剩余算力足够,分配后剩余算力 1。
时刻 5,第 1 个计算机仍然正在计算第 1,4 个任务,剩余算力不足 4,失败。
时刻 6,第 1 个计算机仍然正在计算第 4 个任务,剩余算力足够,且恰好用完。
模拟题,可以发现,每个计算机之间互相不会影响,我们可以用优先队列来维护每一个计算机
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N = 200010;
int n,m;
int s[N];
priority_queue<PII,vector<PII>,greater<PII>> q[N];
int main()
{
cin>>n>>m;
for(int i = 1 ; i <= n ; i++) cin>>s[i];
while(m--)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
while(q[b].size() && q[b].top().x <= a)
{
s[b] += q[b].top().y;
q[b].pop();
}
if(s[b] < d) puts("-1");
else
{
q[b].push({a + c,d});
s[b] -= d;
cout<<s[b]<<endl;
}
}
return 0;
}
J、国际象棋(25分)
众所周知,“八皇后” 问题是求解在国际象棋棋盘上摆放 8 个皇后,使得两两之间互不攻击的方案数。
已经学习了很多算法的小蓝觉得 “八皇后” 问题太简单了,意犹未尽。作为一个国际象棋迷,他想研究在 N×M的棋盘上,摆放 K 个马,使得两两之间互不攻击有多少种摆放方案。
由于方案数可能很大,只需计算答案除以 1000000007 (即 1 0 9 10^9 109+7) 的余数。
如下图所示,国际象棋中的马摆放在棋盘的方格内,走 “日” 字,位于 (x,y)(x,y) 格的马(第 x 行第 y 列)可以攻击 (x+1,y+2)(x+1,y+2)、(x+1,y−2)(x+1,y−2)、(x−1,y+2)(x−1,y+2)、(x−1,y−2)(x−1,y−2)、(x+2,y+1)(x+2,y+1)、(x+2,y−1)(x+2,y−1)、(x−2,y+1)(x−2,y+1) 和 (x−2,y−1)(x−2,y−1) 共 8 个格子。
输入格式
输入一行包含三个正整数 N,M,K 分别表示棋盘的行数、列数和马的个数。
输出格式
输出一个整数,表示摆放的方案数除以 1000000007 (即 1 0 9 10^9 109+7) 的余数。
数据范围
对于 5% 的评测用例,K=1;
对于另外 10% 的评测用例,K=2;
对于另外 10% 的评测用例,N=1;
对于另外 20% 的评测用例,N,M≤6,K≤5;
对于另外 25% 的评测用例,N≤3,M≤20,K≤12;
对于所有评测用例,1≤N≤6,1≤M≤100,1≤K≤20。
输入样例1:
1 2 1
输出样例1:
2
输入样例2:
4 4 3
输出样例2:
276
输入样例3:
3 20 12
输出样例3:
914051446
f[i][a][b][j]
表示:前 i 行 放了 j 匹马,第 i 行 b 是 , i - 1 行是 a
对于每一个位置,有没有马,我们用二进制数表示,0 表示没有马,1 表示有马
状态转移 f[i-1][c][a][j-count(b)]
---->f[i][a][b][j]
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 110,M = 1 << 6,K = 21,MOD = 1e9 + 7;
int n,m,k;
int f[N][M][M][K];
int get_count(int x)
{
int res = 0;
while(x)
{
res++;
x -= x & -x;
}
return res;
}
int main()
{
cin >> n >> m >> k;
f[0][0][0][0] = 1;
for(int i = 1 ; i <= m ; i ++)
for(int a = 0 ; a < 1 << n ; a ++)
for(int b = 0 ; b < 1 << n ; b++)
{
if(b & (a << 2) || a & (b << 2)) continue; // 如果b行和a行的马相差2个位置
for(int c = 0 ; c < 1 << n ; c++)
{
if(c & (a << 2) || a & (c << 2)) continue; // 如果c行和a行的马相差2个位置
if(c & (b << 1) || b & (c << 1)) continue; // 如果c行和b行的马相差1个位置
int t = get_count(b);
for(int j = t ; j <= k ; j++)
f[i][a][b][j] = (f[i][a][b][j] + f[i-1][c][a][j-t]) % MOD;
}
}
int res = 0;
for(int a = 0 ; a < 1 << n ; a ++)
for(int b = 0 ; b < 1 << n ; b ++)
res = (res + f[m][a][b][k]) % MOD;
cout<<res<<endl;
return 0;
}
有点麻,但是和第一场相比,真的不是一个级别