2021“MINIEYE杯”中国大学生算法设计超级联赛(5)

2021“MINIEYE杯”中国大学生算法设计超级联赛(5)

1003.VC Is All You Need

  • 题意

给你一个k维平面,问你是不是随意放n个点都能用k-1条线分隔开

  • 思路

emmmm, 思考一下, n > k + 1都是不行的。。

code:

void solve(){
    ll n,k;
    cin >> n >> k;
    if(n > k+1){
        cout << "No" << endl;
    }else cout << "Yes" << endl;
}

1004.Another String

  • 题意

给定n,k和字符串s, 让你求出从\(1 \to i\)\(i + 1 \to n\)中任意挑选两个子字符串,要求长度相同,并且着一堆字符串中最多有k个字符不同,问你有多少对这样的子字符串

  • 思路

暴力+双指针,求出f[i][j]表示i,j位置为两字符串的左端点,满足要求的最大长度,然后双指针枚举长度。
在纸上模拟一边在通过一些推导可以发现每个位置的贡献是固定的,用差分+两次前缀和便可计算答案。。

code:

int f[N][N];
char str[N];
int ans[N];

void solve(){
    int n,k;
    cin >> n >> k;
    cin >> (str + 1);
    // 枚举右端点
    for(int st = 2;st <= n;st ++) {
        int len = 0;
        int dif = 0;
        // 固定左右端点长度,往后双指针枚举
        for(int i = 1, j = st;j <= n;j ++,i ++) {
            while(dif <= k) {
                dif += str[i + len] != str[j + len];
                len ++; 
            }
            f[i][j] = min(len - 1, min(j - i, n - j + 1));
            len --;dif -= (str[i] != str[j]);
        }
    }
    memset(ans,0,sizeof ans);

    for(int i = 1;i <= n;i ++) {
        for(int j = i + 1;j <= n;j ++) {
            ans[i] ++;
            ans[i + f[i][j]] --;
            ans[j] -= f[i][j];
            ans[j + 1] += f[i][j];
        }
    }
    for(int i = 1;i <= n;i ++) ans[i] += ans[i - 1];
    for(int i = 1;i <= n;i ++) {
        ans[i] += ans[i - 1];
        if(i != n) cout << ans[i] << endl;
    }
}

1006.Cute Tree

  • 题意

给出一个类三叉树的构造方法,让你输出它能建立的节点个数

  • 思路

按着图上的代码打就行了,又不会超时

code:


int a[N];
int tot;

void build(int id,int l,int r) {
    tot ++;
    id = tot;
    if(l == r) {
        return;
    }
    if(r - l + 1 == 1) {
        int mid = l + r >> 1;
        tot += 2;
        return;
    }else {
        int B = l + ceil((r - l + 1) / 3.0) - 1;
        int C = B + r >> 1;
        if(B >= l)
        build(id,l,B);
        if(C >= B + 1)
        build(id,B + 1,C);
        if(r >= C+1);
        build(id,C+1,r);
    }
}

void solve(){
    tot = 0;
    int n;
    cin >> n;
    for(int i = 1;i <= n;i ++) cin >> a[i];
    build(1,1,n);
    cout << tot << endl;
}

1007.Banzhuan

  • 题意

给一个\(n * n * n\)的立方体空间, 你只能用1立方体积的小立方块去填,小立方体放在一个位置,那么它的价值就是\(x * y^2 * z\), 并且,如果你防止的地方的底部(z轴)为空,那么它会一直往下掉。

  • 思路

what
然后, dddd , 套公式了。。

code:

const ll mod = 1e9 + 7;
ll qpow(ll a, ll b, ll mod){
    ll ans = 1;
    while(b){
        if(b & 1)ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
void solve(){
    ll n;
    cin >> n;
    n %= mod;
    ll res = (n%mod*(n+1)%mod*qpow(2,mod-2,mod)%mod)%mod;
    // cnt计算侧面的立方体
    ll cnt = (res%mod*(n%mod*(n+1)%mod*(2*n+1)%mod*qpow(6,mod-2,mod)%mod-1+mod)%mod)%mod;
    // cnt1计算正面
    ll cnt1 = (res%mod-1+mod)%mod*(res%mod)%mod;
    // cnt2底面
    ll cnt2 = ((res%mod)%mod*(n%mod*(n+1)%mod*(2*n+1)%mod)%mod*qpow(6,mod-2,mod)%mod)%mod;
    ll ans = (cnt+cnt1+cnt2 - (res-1+mod)%mod - ((n%mod*(n+1)%mod*(2*n+1)%mod*qpow(6,mod-2,mod)%mod-1+mod)+1ll*2*mod)%mod+ 1ll*5*mod)%mod;//最小值
    ll ans1 =  (n%mod*n%mod*cnt2%mod)%mod; // 最大值
    cout << ans << endl;
    cout << ans1 << endl;
}

1009.Array

  • 题意

给出一个长度为n的序列,满足一对(l,r)及(\(a_l,a_{l+1}···,a_r\))之中,众数出现的次数严格大于其他非众数出现的次数

  • 思路

写了半天的线段树疯狂t,给出的数据倒是能过,我人已傻,占坑

code:

posted @ 2021-08-03 19:57  darker_wxl  阅读(346)  评论(0编辑  收藏  举报
window.onload = function(){ $("#live2dcanvas").attr("style","position: fixed; opacity: 0.7; left: 70px; bottom: 0px; z-index: 1; pointer-events: none;") }