1 solutions

  • 1
    @ 2025-5-6 20:47:02

    此题要点:

    1. 体会区间DP的思想(从小区间合并得到大区间);
    2. 状态的定义;
    3. 初始化的手段
    4. __int128 的用法要掌握。
    #include <iostream>
    using namespace std;
    typedef __int128 LLL;
    
    const int N = 55;
    LLL a[N];
    LLL f[N][N]; // f[i][j]表示凸多边形 (i,j) 的最小划分值
    
    // __int128的输入输出。选你喜欢的背下来,熟练书写。更多写法请自行搜索。
    ostream& operator << (ostream& out, LLL x) {...}
    
    void write(LLL x) {...}
    
    LLL read() {...}
    
    int main() {
    	int n;
    	cin >> n;
    	for (int i = 1; i <= n; i++) a[i] = read();
    
    	for (int len = 3; len <= n; len++) // 状态:区间长度从3开始,2是没意义的。
    		for (int L = 1; L + len - 1 <= n; L++) { // 枚举区间左端点
    			int R = L + len - 1;
    			// 为了避免初始化为无穷,就直接把 k==L+1 这种情况当作 f[L][R] 的初始值。
    			f[L][R] = f[L][L + 1] + f[L + 1][R] + a[L] * a[L + 1] * a[R];
    			for (int k = L + 2; k <= R - 1; k++) // 枚举区间内断点的【绝对】位置
    				f[L][R] = min(f[L][k] + f[k][R] + a[L] * a[k] * a[R], f[L][R]);
    		}
    
    	cout << f[1][n];
    
    	return 0;
    }
    

    下面是 __int128 输入输出的一些写法。选你喜欢的背下来,熟练书写。更多写法请自行搜索,还要掌握 __int128 能参与的运算,以及能在哪些场景和比赛中使用

    ostream& operator << (ostream& out, LLL x) {
    	if (!x) {
    		out << 0;
    		return out;
    	}
    	if (x < 0)x = -x;
    	int stk[110], top = 0;
    	while (x) {
    		stk[++top] = x % 10;
    		x /= 10;
    	}
    	for (int i = top; i >= 1; i--) out << stk[i];
    	return out;
    }
    
    void write(LLL x) {
    	if (x < 0) {
    		putchar('-');
    		x = -x;
    	}
    	if (x > 9) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    LLL read() {
    	LLL x = 0, flag = 1;
    	char ch = getchar();
    	while (!isdigit(ch)) {
    		if (ch == '-') flag = -1;
    		ch = getchar();
    	}
    	while (isdigit(ch)) {
    		x = x * 10 + (ch - '0');
    		ch = getchar();
    	}
    	return x * flag;
    }
    
    • 1

    Information

    ID
    151
    Time
    1000ms
    Memory
    512MiB
    Difficulty
    7
    Tags
    # Submissions
    40
    Accepted
    9
    Uploaded By