“山大地纬杯”第十二届山东省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])
posted @ 2022-10-22 13:26  zyy2001  阅读(62)  评论(0编辑  收藏  举报