“山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛(正式赛)
比赛链接
“山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛(正式赛)
用1~n所有数字用+,-,*,(,),组成计算式使得其得数为17
解题思路
思维
由于任意连续的 \(4\) 个数都可以消为 \(0\),即 \(n+n-3-(n-1)-(n-2)=0\) ,故可以预处理出来满足条件的前 \(4\) 个数,后面每 \(4\) 个数消为 \(0\) 即可
- 时间复杂度:\(O(n)\)
代码
// Problem: Seventeen
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/43685/A
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int n;
string s[]={"","-1","-1","-1","(1+4)*3+2","1*2*5+3+4","1*2*5+4-3+6","2*5+3+4+7-6-1"};
int main()
{
cin>>n;
if(n<4)cout<<s[n];
else if(n<=7)cout<<s[n];
else
{
while(n>7)
{
cout<<n<<'+'<<n-3<<'-'<<n-1<<'-'<<n-2<<'+';
n-=4;
}
cout<<s[n];
}
return 0;
}
Minimum Expression
长度为 \(n\) 的数 \(s\),不含 \(0\),求表达式加 \(m\) 个 \(+\) 的最小值
解题思路
dp,思维
设 \(f[i][j]\) 表示前 \(i\) 个数中加 \(j\) 个 \(+\) 的最小值,则有 \(f[i][j]=min{f[k][j-1]+s[k+1][i]}\) 其中 \(s[i][j]\) 表示数 \(s\) 中 \(i\sim j\) 表示的数
由于数中没有 \(0\),所以为了最小,所分配的 \(j+1\) 个数长度约平均越优,直接暴力枚举 \(i,j\),枚举 \(k\) 时只要枚举 \(O(n/m)\) 的长度即可
- 时间复杂度:\(O(n^2)\)
代码
n, m = map(int,input().split(' '))
s = input()
N = 1010
INF = 10**1001
a = [[0 for i in range(N)] for j in range(N)]
f = [[INF for i in range(N)] for j in range(N)]
def get(c):
return int(c)
for i in range(1, n + 1):
for j in range(i, n + 1):
a[i][j] = a[i][j - 1] * 10 + get(s[j - 1])
for i in range(1, n + 1):
for j in range(0, min(i, m + 1)):
if j == 0:
f[i][j] = a[1][i]
else:
f[i][j] = INF
for k in range(max(1,i-n//m*2), i):
if f[i][j] > f[k][j - 1] + a[k + 1][i]:
f[i][j] = f[k][j - 1] + a[k + 1][i]
print(f[n][m])