zoukankan      html  css  js  c++  java
  • 选球游戏 题解———2019.10.19

    选球游戏( game )
    时间限制:3s
    空间限制:512MB
    编译时开启 O2 优化开关
    【问题描述】
    华华和秀秀在玩游戏。在他们面前有!个球排成一排,从左到右按 1 到!编号。每个球有一
    个可正可负的权值。 每一轮, 秀秀会选定一个区间[#,%], 将编号在这个区间内的所有球的权值
    加上一个值', 或者将编号在这个区间内的所有球的权值都设为其相反数。 华华则需从这!个球
    中选出(个球来,他的得分为这(个球的权值的乘积。
    华华每次都能快快地找出得分最优的选球方案来。秀秀想了想,决定提升游戏难度。她每
    次会选定一个区间[#,%],然后询问华华在这个区间内选出((1 ≤ ( ≤ 10)个球的所有方案的得
    分之和。
    这下可把华华难倒了,于是华华找到了聪明的你。你能帮帮他嘛?
    由于所有方案的得分之和可能很大,你只需要输出得分之和对1000000007(10 / + 7)取模
    的结果(负数请加上10 / + 7变成非负数)即可。
    【输入格式】
    从文件 game.in 中读入数据。
    输入第一行包含两个正整数!,1,分别表示球的个数和秀秀的操作条数。
    接下来一行包含!个空格隔开的整数,表示每个球初始的权值。
    接下来1行,每行表示秀秀的一个操作。
    若该行形如“1 # % '”,则表示秀秀将编号属于[#,%]的所有球的权值都加上了';
    若该行形如“2 # %”,则表示秀秀将编号属于[#,%]的所有球的权值都置为了其相反数;
    若该行形如“3 # % (”,则表示华华需要回答从[#,%]中选出(个球的所有取球方案的得分之
    和。
    【输出格式】
    输出文件到 game.out 中。
    对于秀秀宝宝的每一个询问操作,输出一行,表示该询问的答案。
    【样例输入】
    10 9
    3 6 7 4 6 1 6 7 2 6
    3 5 7 3
    1 1 7 -9
    1 2 3 5
    3 2 6 1
    2 5 8
    3 5 7 3
    2 2 3
    3 1 10 2
    3 1 2 2
    【样例输出】
    36
    999999996
    72
    999999885
    12
    【样例说明】
    第一个询问:6×1×6 = 36
    第二个询问:
    询问前各个球的权值为:-6 2 3 -5 -3 -8 -3 7 2 6
    2 + 3 + −5 + −3 + −8 = −1111 + (10 / + 7) = 999999996
    第三个询问:
    询问前各个球的权值为:-6 2 3 -5 3 8 3 7 2 6
    3×8×3 = 72

    考虑用线段树来完成此题。对于每个节点我们维护一个f[i](i in [1, 10]),表示这个节点所对应区间选i个球的答案。
    考虑如何合并两个节点lc,rc。f[i] = sum(lc.f[j] * rc.f[i-j]) j in [0,i]
    对于取相反数操作,只有当i是奇数时,才会改变f[i]的符号。
    对于一段区间+c的操作,设这段区间的长度为len,则新的f[i]为sum (f(j) * c^{i-j} * C(len - j, i - j)) jin [0,i] 其中C(n,m)表示n个数中选m个的组合数
    这样我们就可以套用区间修改区间询问的线段树来解决这道题了,时间复杂度为O(c^2nlogn)

    #include <cstdio>
    #include <cstdlib>
    #define MOD 1000000007
    #define N 100005
    typedef long long LL; 
    using namespace std;
    struct Node {
        LL f[11];
    }node[N * 4];
    LL a[N], lazy1[N * 4];
    bool lazy2[N * 4];
    LL C[N][11];
    
    Node merge(Node lc, Node rc) {
        Node o;
        o.f[0] = 1;
        for (int i = 1; i <= 10; i++) {
            o.f[i] = 0;
            for (int j = 0; j <= i; j++)
                o.f[i] = (o.f[i] + lc.f[j] * rc.f[i - j] % MOD) % MOD;
        }
        return o;
    }
    
    void build(int o, int l, int r) {
        if (l == r) {
            for (int i = 0; i <= 10; i++) node[o].f[i] = 0;
            node[o].f[0] = 1;
            node[o].f[1] = (a[l] % MOD + MOD) % MOD;
            return ;
        }
        int mid = (l + r) >> 1;
        build(o * 2, l, mid);
        build(o * 2 + 1, mid + 1, r);
        node[o] = merge(node[o * 2], node[o * 2 + 1]);
        return ;
    }
    
    void update1(int o, int l, int r, int c) {
        int len = r - l + 1;
        LL ff[11];
        for (int i = 0; i <= 10; i++) ff[i] = node[o].f[i];
        for (int i = 1; i <= 10; i++) {
            node[o].f[i] = 0;
            LL t = 1;
            for (int j = 0; j <= i; j++) {
                LL tmp = ff[i - j] * C[len - (i - j)][j] % MOD * t % MOD;
                node[o].f[i] = (node[o].f[i] + tmp) % MOD;
                t = t * c % MOD;
            }
        }
        return ;
    }
    
    void push_down(int o, int l, int r) {
        int mid = (l + r) >> 1;
        if (lazy1[o]) {
            if (lazy2[o * 2])
                lazy1[o * 2] = (lazy1[o * 2] + MOD - lazy1[o]) % MOD;
            else 
                lazy1[o * 2] = (lazy1[o * 2] + lazy1[o]) % MOD;
            if (lazy2[o * 2 + 1])
                lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + MOD - lazy1[o]) % MOD;
            else 
                lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + lazy1[o]) % MOD;
            update1(o * 2, l, mid, lazy1[o]);
            update1(o * 2 + 1, mid + 1, r, lazy1[o]);
            lazy1[o] = 0;
        }
        if (lazy2[o]) {
            lazy2[o * 2] ^= 1;
            lazy2[o * 2 + 1] ^= 1;
            for (int j = 1; j <= 10; j += 2) {
                node[o * 2].f[j] = MOD - node[o * 2].f[j];
                node[o * 2 + 1].f[j] = MOD - node[o * 2 + 1].f[j];
            }
            lazy2[o] = 0;
        }
    }
    
    void modify1(int o, int l, int r, int ll, int rr, int c) {
        if (ll <= l && rr >= r) {
            if (lazy2[o]) lazy1[o] = (lazy1[o] + MOD - c) % MOD;
            else lazy1[o] = (lazy1[o] + c) % MOD;
            update1(o, l, r, c);
            return ;
        }
        int mid = (l + r) >> 1;
        push_down(o, l, r);
        if (ll <= mid) modify1(o * 2, l, mid, ll, rr, c);
        if (rr > mid) modify1(o * 2 + 1, mid + 1, r, ll, rr, c);
        node[o] = merge(node[o * 2], node[o * 2 + 1]);
        return ;
    }
    
    void modify2(int o, int l, int r, int ll, int rr) {
        if (ll <= l && rr >= r) {
            for (int i = 1; i <= 10; i += 2) node[o].f[i] = MOD - node[o].f[i];
            lazy2[o] ^= 1;
            return ;
        }
        int mid = (l + r) >> 1;
        push_down(o, l, r);
        if (ll <= mid) modify2(o * 2, l, mid, ll, rr);
        if (rr > mid) modify2(o * 2 + 1, mid + 1, r, ll, rr);
        node[o] = merge(node[o * 2], node[o * 2 + 1]);
        return ;
    }
    
    Node query(int o, int l, int r, int ll, int rr) {
        if (ll <= l && rr >= r) 
            return node[o];
        int mid = (l + r) >> 1;
        push_down(o, l, r);
        if (rr <= mid) return query(o * 2, l, mid, ll, rr);
        if (ll > mid) return query(o * 2 + 1, mid + 1, r, ll, rr);
        Node lc = query(o * 2, l, mid, ll, rr);
        Node rc = query(o * 2 + 1, mid + 1, r, ll, rr);
        return merge(lc, rc);
    }
    
    int main(int argc, char ** argv) {
        // freopen("game.in", "r", stdin);
        // freopen("game.out", "w", stdout);
        int n, m;
        scanf("%d %d", &n, &m);
        C[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            C[i][0] = 1;
            for (int j = 1; j <= 10; j++) 
                C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
        }
        for (int i = 1; i <= n; i++) 
            scanf("%d", &a[i]);
        build(1, 1, n); 
        for (int i = 1; i <= m; i++) {
    
            int l, r, opt;
            scanf("%d%d%d",&opt, &l, &r);
            if (opt == 1) {
                int c;
                scanf("%d", &c);
                c = (c % MOD + MOD) % MOD;
                modify1(1, 1, n, l, r, c);
            }
            else if (opt == 2) {
                modify2(1, 1, n, l, r);
            }
            else {
                int k;
                scanf("%d", &k);
                Node o = query(1, 1, n, l, r);
                printf("%d
    ", o.f[k] % MOD);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 阮小二买彩票
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 传染病控制
    Java实现 蓝桥杯VIP 算法提高 企业奖金发放
    Java实现 蓝桥杯VIP 算法提高 企业奖金发放
    让程序后台隐藏运行
    只要你喜欢,并且可以养家糊口,就是好的
  • 原文地址:https://www.cnblogs.com/ydclyq/p/11705816.html
Copyright © 2011-2022 走看看