第一题 最小等式
提交文件:
equation.cpp
输入文件:
equation.in
输出文件:
equation.out
时间空间限制:
1 秒, 512 MB
黑板上有四个数 a,b,c,d,你需要在数与数之间填上运算符(加或减或乘或除),使得等式运算后的结果是
整数,并且绝对值最小。注意乘除的运算优先级高于加减,并且相同优先级的运算符从左到右依次运算。请
问算式结果的绝对值最小是多少?
输入格式
一行读入三个正整数 a, b, c, d。
输出格式
输出一个数字,表示绝对值最小是多少。
样例数据
equation.in
equation.out
2 4 2 5
1
数据范围
对于 20% 的数据,1 ≤ a, b, c, d ≤ 20。
对于 100% 的数据,1 ≤ a, b, c, d ≤ 1000;
核心思路
暴力递归求解
100pt
#include<bits/stdc++.h>
using namespace std;
long double a,b,c,d,ans = -1;
char fu[11],fz[11] = {' ','+','-','*','/'};
long double Count2(long double a,char F_1,long double b){
// cout<<a<<F_1<<b<<endl;
if(F_1 == '*') return a*b;
if(F_1 == '/') return a/b;
if(F_1 == '+') return a+b;
if(F_1 == '-') return a-b;
}
long double Count3(long double a,char F_1,long double b,char F_2,long double c){
//cout<<a<<F_1<<b<<F_2<<c<<endl;
if(F_1 == '*') return Count2(a*b,F_2,c);
if(F_1 == '/') return Count2(a/b,F_2,c);
if(F_2 == '*') return Count2(a,F_1,b*c);
if(F_2 == '/') return Count2(a,F_1,b/c);
if(F_1 == '+') return Count2(a+b,F_2,c);
if(F_1 == '-') return Count2(a-b,F_2,c);
}
long double Count4(long double a,char F_1,long double b,char F_2,long double c,char F_3,long double d ){
//cout<<a<<F_1<<b<<F_2<<c<<F_3<<d<<endl;
if(F_1 == '*') return Count3(a*b,F_2,c,F_3,d);
if(F_1 == '/') return Count3(a/b,F_2,c,F_3,d);
if(F_2 == '*') return Count3(a,F_1,b*c,F_3,d);
if(F_2 == '/') return Count3(a,F_1,b/c,F_3,d);
if(F_3 == '*') return Count3(a,F_1,b,F_2,c*d);
if(F_3 == '/') return Count3(a,F_1,b,F_2,c/d);
if(F_1 == '-') return Count3(a-b,F_2,c,F_3,d);
if(F_1 == '+') return Count3(a+b,F_2,c,F_3,d);
if(F_2 == '-') return Count3(a,F_1,b-c,F_3,d);
if(F_2 == '+') return Count3(a,F_1,b+c,F_3,d);
if(F_3 == '-') return Count3(a,F_1,b,F_2,c-d);
if(F_3 == '+') return Count3(a,F_1,b,F_2,c+d);
}
bool pd(long double a){
if(a-int(a) == 0)return 1;
return 0;
}
void dfs(int x){
if(x == 3+1){
//cout<<a<<fu[1]<<b<<fu[2]<<c<<fu[3]<<d<<"="<<Count4(a,fu[1],b,fu[2],c,fu[3],d)<<endl;
if(pd(Count4(a,fu[1],b,fu[2],c,fu[3],d))){
if(ans == -1)ans = abs(Count4(a,fu[1],b,fu[2],c,fu[3],d));
else ans = min(ans,abs(Count4(a,fu[1],b,fu[2],c,fu[3],d)));
}
return ;
}
for(int i = 1;i <= 4;i++){
fu[x] = fz[i];
dfs(x+1);
}
}
int main(){
//freopen("equation.in","r",stdin);
//freopen("equation.out","w",stdout);
cin>>a>>b>>c>>d;
dfs(1);
cout<<ans;
}
第二题 求和计算
提交文件:
calculate.cpp
输入文件:
calculate.in
输出文件:
calculate.out
时间空间限制:
2 秒, 512 MB
给定 n, k, a, b, c。
计算下式对 998244353 取模的结果。
n
∑
i=1
(a i + b i + c i ) k
输入格式
读入数据共一行, 包含 5 个整数 n, k, a, b, c。
输出格式
输出一行,包含一个正整数,表示所求的答案对 998244353 取模的结果。
样例数据
calculate.in
calculate.out
2 2 1 2 3
232
数据范围
对于 30% 的数据,b = c = 0。
对于 60% 的数据,c = 0。
对于 100% 的数据,1 ≤ n ≤ 109 , 1 ≤ k ≤ 1000, 0 ≤ a, b, c < 998244353
没推出公式,寄了。0pt
第三题 数组划分
提交文件:
divide.cpp
输入文件:
divide.in
输出文件:
divide.out
时间空间限制:
1 秒, 512 MB
给定一个长度为 n 的数组 a,将其划分为恰好 k 个首尾相接的区间,每个区间的价值是区间最大值减区
间最小值。数组的总价值是所有区间的价值之和。求当 k = 1, 2, 3, ⋯, n 的时候,最大的数组总价值分别是
多少。
输入格式
第一行读入一个正整数 n。
第二行 n 个数字 ai,表示数组 a。
输出格式
输出共 n 行。
第 i 行一个整数表示 k=i 时的答案。
样例数据
divide.in
divide.out
5
1 2 3 4 5
4
3
2
1
0
数据范围
对于 20% 的数据,1 ≤ n ≤ 10。
对于 40% 的数据,1 ≤ n ≤ 400。
对于 100% 的数据,1 ≤ n ≤ 5000, 1 ≤ ai ≤ 104。
打了个暴力,解出了40%。感觉正解是要加一个四边形不等式优化。40pt
#include <bits/stdc++.h>
using namespace std;
const long long maxn = 5010;
int n;
long long dp[5010][5010], a[10001], o[5011][5011];
struct ST {
long long lg[maxn], st_min[maxn][19], st_max[maxn][19];
void init(long long a[], int n) {
lg[0] = -1;
for (int i = 1; i <= n; i++) {
lg[i] = lg[i / 2] + 1;
st_min[i][0] = st_max[i][0] = a[i];
}
for (int j = 1; j <= lg[n]; j++) {
for (int i = 1; i <= n; i++) {
st_min[i][j] = min(st_min[i][j - 1], st_min[i + (1 << j - 1)][j - 1]);
st_max[i][j] = max(st_max[i][j - 1], st_max[i + (1 << j - 1)][j - 1]);
}
}
}
long long qmin(int l, int r) {
int k = lg[r - l + 1];
return min(st_min[l][k], st_min[r - (1 << k) + 1][k]);
}
long long qmax(int l, int r) {
int k = lg[r - l + 1];
return max(st_max[l][k], st_max[r - (1 << k) + 1][k]);
}
} A1;
void slove() {
memset(dp, -1, sizeof(dp));
for (int i = 1; i <= n; i++) {
dp[i][0] = A1.qmax(1, i) - A1.qmin(1, i);
for (int k = 1; k <= n; k++) {
for (int j = i; j >= 1; j--) {
if (k - 1 > j - 1 - 1)
break;
dp[i][k] = max((long long)dp[i][k], dp[j - 1][k - 1] + (A1.qmax(j, i) - A1.qmin(j, i)));
}
}
}
}
int main() {
freopen("divide.in", "r", stdin);
freopen("divide.out", "w", stdout);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
A1.init(a, n);
slove();
for (int i = 0; i < n; i++) {
cout << dp[n][i] << endl;
}
return 0;
}
第四题 序列统计
提交文件:
sequence.cpp
输入文件:
sequence.in
输出文件:
sequence.out
时间空间限制:
2 秒, 512 MB
给定一个长度为 n 的序列 a,里面每一个元素的都是 [1,m] 的正整数,且保证每个数字都至少出现了一
次。对于 i=1...m 分别求出最短长度的区间,使得区间包含 {1,2,3,...i}。
输入格式
第一行读入两个个正整数 n, m。
第二行 n 个数字 ai,表示序列 a。
输出格式
输出共 m 行。
第 i 行一个整数表示包含 {1,2,3,...i} 的最短区间的长度。
样例数据
sequence.in
sequence.out
5 3
1 3 2 3 1
1
3
3
数据范围
对于 30% 的数据,1 ≤ n, m ≤ 5 · 103。
对于 70% 的数据,1 ≤ n, m ≤ 105。
对于 100% 的数据,1 ≤ n, m ≤ 5 · 105 , 1 ≤ ai ≤ m。
一直在想第三题的优化,没看第四题。
0pt.
总分140pt。
下午,等评讲,会出个正解。笑。
文章介绍了解决四则运算题目中的最小绝对值问题,通过递归实现并探讨了数组划分中的优化策略。
2312

被折叠的 条评论
为什么被折叠?



