zoukankan      html  css  js  c++  java
  • 2020牛客多校第八场E-Enigmatic Partition

    https://ac.nowcoder.com/acm/contest/5673/E

    题意

    定义(f(n))为拆分n为(a_1,a_2 dots a_m)满足相邻两个数差值不能超过1,且最大值和最小值差值为2的拆分个数,T次询问,每次询问(sumlimits_{i=l}^r f(i))

    题解

    拆分肯定由三种连续的数构成,枚举(l)去初始化(f(n)),具体方法是枚举l的数量(i),然后枚举(m=l+1)的数量(j),则(f[i*l+j*m]=(j-1)/2)因为可以将两个(l+1)拆分为一个(l)和一个(l+2),一共可以拆分((j-1)/2)次,这种情况下,(l)的数量一定大于r的数量,所以要反过来再枚举一遍(lle r)的情况。

    这部分的复杂度是调和级数的,但是在(l)很小的时候运行很慢,可以用完全背包优化(l<50)的情况

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    struct READ {
        inline char read() {
        #ifdef _WIN32
            return getchar();
        #endif
            static const int IN_LEN = 1 << 18 | 1;
            static char buf[IN_LEN], *s, *t;
            return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
        }
        template <typename _Tp> inline READ & operator >> (_Tp&x) {
            static char c11, boo;
            for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
                if(c11 == -1) return *this;
                boo |= c11 == '-';
            }
            for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
            boo && (x = -x);
            return *this;
        }
    } in;
    
    const int N = 1e5 + 50;
    ll f[N];
    ll dp[N];
    int a[N];
    int main() {
        for (int l = 50; l < N; l++) {
            int mid = l + 1;
            int r = l + 2;
            for (int i = 1; i * l < N; i++) {
                for (int j = 3; j * mid + i * l < N; j++) {
                    f[i*l+j*mid] += (j - 1) / 2;
                }
            }
            for (int i = 0; i * r < N; i++) {
                for (int j = 3; i * r + j * mid < N; j++) {
                    f[i*r+j*mid] += (j - 1) / 2;
                }
            }
        }
        for (int l = 1; l < 50; l++) {
            memset(dp, 0, sizeof(dp));
            a[1] = l; a[2] = l + 1; a[3] = l + 2;
            int x = 3 * l + 3;
            dp[x] = 1;
            for (int i = 1; i <= 3; i++) {
                for (int j = x + a[i]; j < N; j++) {
                    dp[j] += dp[j - a[i]];
                }
            }
            for (int i = 1; i < N; i++) f[i] += dp[i];
        }
        for (int i = 1; i < N; i++) f[i] += f[i - 1];
        int t; in >> t;
        int cse = 0;
        while (t--) {
            int l, r; in >> l >> r;
            printf("Case #%d: %lld
    ", ++cse, f[r] - f[l - 1]);
        }
        return 0;
    }
    
  • 相关阅读:
    sql评估已过期
    解决电脑弹窗
    清除电脑缓存,解决电脑卡
    vant小程序实现表单提交(时间组件,弹出层组件)
    jquery每两秒执行函数
    git pull遇到错误:error: Your local changes to the following files would be overwritten by merge:
    阿里云服务器http转https
    微信小程序错误码40029
    1366:Incorrect string value: 'xE4xBBx8AxE5xA4xA9' for column 'content' at row 1 [ SQL语句 ] :
    每日一题 为了工作 2020 0308 第六题
  • 原文地址:https://www.cnblogs.com/artoriax/p/13632881.html
Copyright © 2011-2022 走看看