题目链接
4803. 满足的数 简单
4804. 构造矩阵 中等
4805. 加减乘 困难
题目描述
4803. 满足的数
给定 n
个不超过 5 的正整数 a1,a2,…,an
。
不妨设 S=a1+a2+…+an
。
请你统计,一共有多少个不同的整数 x 能够同时满足以下所有条件:
- 1≤x≤51≤x≤51≤x≤5
- (S+x)mod(n+1)≠1(S+x)mod(n+1)≠1(S+x)mod(n+1)=1输入格式第一行包含整数
n
。
输入格式
第一行包含整数 n
。
第二行包含 n
个正整数 a1,a2,…,an
。
输出格式
一个整数,表示满足条件的 x
的数量。
数据范围
- 1≤n≤1001≤n≤1001≤n≤100
- 1≤ai≤51≤a_i≤51≤ai≤5
输入样例1:
1
1
输出样例1:
3
输入样例2:
1
2
输出样例2:
2
输入样例3:
2
3 5
输出样例3:
3
时间复杂度:O(n)O(n)O(n)
代码:
#include<iostream>
#include<algorithm>using namespace std;const int N = 110;
int a[N];int main(){int n;cin>>n;int sum = 0;for(int i = 1;i <= n;i++){cin>>a[i];sum += a[i];}int ans = 0;for(int x = 1;x <= 5;x++){if((sum + x) % (n + 1) != 1) ans++;}cout<<ans<<endl;return 0;
}
4804. 构造矩阵
给定一个 mmm行 nnn 列的 01
矩阵 B。
请你构造一个 mmm 行 nnn 列的 01
矩阵 A。
矩阵的行编号为 1∼m1∼m1∼m,列编号为 1∼n1∼n1∼n。
BijB_{ij}Bij 表示矩阵 B 中第 i 行第 j 列的元素。
要求,构造的矩阵 A 满足,对于每一个 BijB_{ij}Bij:
-
如果 Bij=0B_{ij}=0Bij=0,则矩阵 A 中第 i 行的 nnn 个元素以及第 j 列的 mmm 个元素总共 n+mn+mn+m 个元素必须全都为 0。
-
如果 Bij=1B_{ij}=1Bij=1,则矩阵 A 中第 i 行的 nnn 个元素以及第 j 列的 mmm 个元素总共 n+mn+mn+m 个元素不能全都为 0。
输入格式
第一行包含两个整数 m,nm,nm,n。
接下来 mmm 行,每行包含 nnn 个整数 0 或 1,其中第 i 行第 j 列的整数表示 BijB_{ij}Bij。
输出格式
如果不存在满足条件的矩阵 A,则输出一行 NO
即可。
否则,第一行输出 YES
,接下来 mmm 行,每行输出 nnn个整数,用来表示矩阵 A。
如果答案不唯一,则输出任意合理答案均可。
数据范围
- 1≤m,n≤1001≤m,n≤1001≤m,n≤100
输入样例1:
2 2
1 0
0 0
输出样例1:
NO
输入样例2:
2 3
1 1 1
1 1 1
输出样例2:
YES
1 1 1
1 1 1
输入样例3:
2 3
0 1 0
1 1 1
输出样例3:
YES
0 0 0
0 1 0
分析:
我们先将整个数组初始化为全部是 1
,我们直接先处理所有 Bij=0B_{ij} = 0Bij=0 的情况,将对应的行和列全部置为0。
接着我们再处理 Bij=1B_{ij} = 1Bij=1 的情况,对于其对应行 和 列的元素之和 如果等于0,就直接打印 NO
返回;否则最后打印 YES
,再打印数组
时间复杂度:O(n2)O(n^2)O(n2)
代码:
#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;const int N = 110;int n,m;
int a[N][N],b[N][N];//对应行 和 列都更新为0
void update(int x,int y){for(int j = 1;j <= n;j++) b[x][j] = 0;for(int i = 1;i <= m;i++) b[i][y] = 0;
}//获取对应行 和 列的元素之和
int getsum(int x,int y){int sum = 0;for(int j = 1;j <= n;j++) sum += b[x][j];for(int i = 1;i <= m;i++) sum += b[i][y];//因为 + 了两次 b[x][y],所以要减一次return sum - b[x][y];
}int main(){cin>>m>>n;for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++) {cin>>a[i][j];b[i][j] = 1;}}for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){if(!a[i][j]) update(i,j);}}for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){if(a[i][j]){int sum = getsum(i,j);if(sum == 0){puts("NO");return 0;}}}}puts("YES");for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){cout<<b[i][j]<<" ";}puts("");}return 0;
}
4805. 加减乘
规定两种数字操作:
- 加减操作,将数字加 1 或减 1,代价为
x
。 - 乘法操作,将数字乘 2,代价为
y
。
每种操作的使用次数不限。
请你计算,通过上述操作,将 0 变为 n,所需花费的最小代价。
输入格式
共一行,包含三个整数 n,x,yn,x,yn,x,y。
输出格式
一个整数,表示最小代价。
数据范围
- 1≤n≤107,1≤x,y≤1091≤n≤10^7,1≤x,y≤10^91≤n≤107,1≤x,y≤109
输入样例1:
8 1 1
输出样例1:
4
输入样例2:
2 3
1 1 1
1 1 1
输出样例2:
8 1 10
输入样例3:
8
分析:
本题使用 动态规划 求解。我们定义 f(i)f(i)f(i) 是从 0 ~ n
的最小代价。
状态转移:
- f(i)=f(i−1)+xf(i) = f(i-1) + xf(i)=f(i−1)+x
- 当
i
是偶数时,f(i)=min(f(i),f(i/2)+y)f(i) = min( f(i) , f(i/2) + y )f(i)=min(f(i),f(i/2)+y) - f(i−1)=min(f(i−1),f(i)+x)f(i-1) = min( f(i - 1) , f(i) + x)f(i−1)=min(f(i−1),f(i)+x) (因为 f(i−1)f(i-1)f(i−1) 可能还会由 f(i)f(i)f(i) 更新而来,所以要等 f(i)f(i)f(i) 先更新完毕)
时间复杂度:O(n)O(n)O(n)
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
using LL = long long;int n,x,y;const int N = 1e7+10;
//用 long long 防止溢出
LL f[N];int main(){cin>>n>>x>>y;memset(f,0,sizeof f); //之所以是 1 ~ n + 1 ,是因为当 i = n 时,f[n] 还可能会由 f[n+1] + x 更新而来 for(int i = 1;i <= n+1;i++){f[i] = f[i-1] + x;if(i % 2 == 0) f[i] = min(f[i],f[i/2] + y);f[i-1] = min(f[i-1],f[i] + x);}cout<<f[n]<<endl;return 0;}