繁华模拟赛 ljw分雕塑

/*
用f[i][k]表示考虑到第i个雕塑,分成k组,可不可行(这是一个bool类型的数组)
转移:
f[i][k]=f[j][k-1],sum[i]-sum[j]合法
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;

typedef long long ll;
const int max_n = 2010;
const ll inf = 1e15;

inline int getnum() {
    int ans = 0; char c; bool flag = false;
    while (!isdigit(c = getchar()) && c != ‘-‘);
    if (c == ‘-‘) flag = true; else ans = c - ‘0‘;
    while (isdigit(c = getchar())) ans = ans * 10 + c - ‘0‘;
    return ans * (flag ? -1 : 1);
} 

int a[max_n], limit_A, limit_B, n;;

namespace part1 {
    const int max_n_small = 110;
    bool able[max_n_small][max_n_small];

    inline bool check(ll ba, ll tar) {
        memset(able, 0, sizeof(able));
        able[0][0] = true;

        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= limit_B; j++) {
                ll sum = a[i];
                for (int k = i - 1; k >= 0; k--) {
                    if (able[k][j - 1] && (sum | ba) < tar) {
                        able[i][j] = true;
                        break;
                    }
                    sum += a[k];
                }
            }

        for (int i = limit_A; i <= limit_B; i++)
            if (able[n][i])
                return true;
        return false;
    }

    inline void solve() {
        ll sum = 0;
        for (int i = 1; i <= n; i ++)
            sum += a[i];
        sum <<= 1;
        int max_bit = 0;
        for (; sum >> max_bit; max_bit++);
        max_bit--;

        ll ans = 0;
        for (int i = max_bit; i >= 0; i--) {
            ll tar = ans | (1LL << i);
            if (!check(ans, tar))
                ans += (1LL << i);
        }
        cout << ans << endl;
    }
}

namespace part2 {
    const int max_n_small = 2010;
    bool able[max_n_small];
    int f[max_n_small];

    inline bool check(ll ba, ll tar) {
        memset(able, 0, sizeof(able));
        memset(f, 0x7f, sizeof(f));
        able[0] = true;
        f[0] = 0;

        for (int i = 1; i <= n; i++) {
            ll sum = a[i];
            for (int k = i - 1; k >= 0; k--) {
                if (able[k] && (sum | ba) < tar) {
                    able[i] = true;
                    f[i] = min(f[i], f[k] + 1);
                }

                sum += a[k];
            }
        }

        if (able[n] && f[n] <= limit_B)
            return true;
        else
            return false;
    }

    inline void solve() {
        ll sum = 0;
        for (int i = 1; i <= n; i ++)
            sum += a[i];
        sum <<= 1;
        int max_bit = 0;
        for (; sum >> max_bit; max_bit++);
        max_bit--;

        ll ans = 0;
        for (int i = max_bit; i >= 0; i--) {
            ll tar = ans | (1LL << i);
            if (!check(ans, tar))
                ans += (1LL << i);
        }
        cout << ans << endl;
    }
}

int main() {
    freopen("sculpture.in", "r", stdin);
    freopen("sculpture.out", "w", stdout);
    n = getnum(); limit_A = getnum(); limit_B = getnum();
    for (int i = 1; i <= n; i++) a[i] = getnum();

    if (n > 100)
        part2::solve();
    else
        part1::solve();
}
时间: 2025-01-02 17:40:32

繁华模拟赛 ljw分雕塑的相关文章

繁华模拟赛 ljw搭积木

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 6005; int n,x[maxn]; int cmd,cnt,ans,max_x; int main(){ freopen("box.in","r"

2018/3/9 省选模拟赛 0分

第二题模拟扫一遍就可以过,不能更划算了.q=1的30分写的比100分还麻烦,有趣哦. 破暴力40分也没什么可写了,日常辣鸡吃枣药丸. 原文地址:https://www.cnblogs.com/137shoebills/p/8533870.html

[繁华模拟赛]Evensgn 剪树枝

Evensgn 剪树枝 题目 繁华中学有一棵苹果树.苹果树有 n 个节点(也就是苹果),n − 1 条边(也就 是树枝).调皮的 Evensgn 爬到苹果树上.他发现这棵苹果树上的苹果有两种:一 种是黑苹果,一种是红苹果.Evensgn 想要剪掉 k 条树枝,将整棵树分成 k + 1 个 部分.他想要保证每个部分里面有且仅有一个黑苹果.请问他一共有多少种剪树枝 的方案? INPUT 第一行一个数字 n,表示苹果树的节点(苹果)个数. 第二行一共 n − 1 个数字 p0, p1, p2, p3,

繁华模拟赛 Vicent与游戏

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<stack> #include<cstdlib> #inc

2018/3/19 模拟赛 35分

T1 不会计算几何弃疗了. T2 写了个bitset结果还不如不优化(手动滑稽),因为测样例开小了空间忘了开回去所以0分. 正解是FFT,不会FFT.. T3 暴力35分,正解倍增floyd,学长还讲过但是还是错了,又多了一个要学的知识点. 原文地址:https://www.cnblogs.com/137shoebills/p/8602386.html

繁华模拟赛 Evensgn的债务

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #define ll int using namespace std; const int maxn = 1000005; ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(

繁华模拟赛 找十字架

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; int n; char s[205][205],cmd; int main(){ freopen("puzzle.in","r",stdin); freopen("puzzle

繁华模拟赛 Vincent的城堡

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll mod = 1000000007; ll n,k,c[20][20]; ll ansa,ansb,ans; void get_c(){ for(int i = 1;i

繁华模拟赛 Evensgn玩序列

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 5000; int n,a[maxn],b[maxn],c[maxn],rka[maxn],rkb[maxn],rkc[maxn]; bool visa[maxn],visb[maxn],vi