CSP-S模拟赛赛时记录(2023,9,30)

第一题 最小等式

提交文件 :
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 10 9 , 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 个数字 a i ,表示数组 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 a i 10 4
打了个暴力,解出了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 个数字 a i ,表示序列 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 · 10 3
对于 70 % 的数据, 1 n, m 10 5
对于 100 % 的数据, 1 n, m 5 · 10 5 , 1 a i m
一直在想第三题的优化,没看第四题。
0pt.
总分140pt。
下午,等评讲,会出个正解。笑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值