[jzoj]4271. 【NOIP2015模拟10.27】魔法阵(37种转移的dp)

  • 题意不说

  • 应该这辈子都不会忘记了...

  • 这是我人生中做的最SB的一道DP题.

  • 真的打的我心态崩了。。。。

  • 可是竟然被我调出来了。。。。。

  • 也是没谁了...

  • 我们设\(F[i][j][S]\)表示到第\(i\)层,然后放了\(j\)个三角形,四个方向是否可以继续拓展的状态为\(S\).

  • 然后分十五种情况进行转移.

  • 每种转移里面再分类讨论。

  • 然后数了数,总共有37种转移方式...

  • 于是就是7k的代码....

#include <iostream>
#include <cstring>
#include <cstdio>

#define F(i, a, b) for (int i = a; i <= b; i++)
#define add(a, b) ((a) = (a + b) % Mo)
#define Mo 1000000007

using namespace std;

int n, k, F[210][410][16], D[15][15], E[15][15];

void Init() {
    scanf("%d %d", &n, &k);

    F[0][0][0] = 1;

    F[0][1][1] = 1;
    F[0][1][2] = 1;
    F[0][1][4] = 1;
    F[0][1][8] = 1;
    F[0][1][0] = 4;

    F[0][2][3] = 1;
    F[0][2][6] = 1;
    F[0][2][12] = 1;
    F[0][2][9] = 1;
    F[0][2][1] = 2;
    F[0][2][2] = 2;
    F[0][2][4] = 2;
    F[0][2][8] = 2;
    F[0][2][5] = 1;
    F[0][2][10] = 1;
    F[0][2][0] = 2;

    F[0][3][7] = 1;
    F[0][3][11] = 1;
    F[0][3][13] = 1;
    F[0][3][14] = 1;
    F[0][3][3] = 1;
    F[0][3][6] = 1;
    F[0][3][12] = 1;
    F[0][3][9] = 1;

    F[0][4][15] = 1;
}

void GetMul() { 
    D[0][0] = 1;
    F(i, 1, 14)
        F(j, 1, 14)
            D[i][j] = (D[i - 1][j] + D[i - 1][j - 1]) % Mo;
    
    E[0][0] = 1;
    F(i, 0, 13)
        F(j, 0, 13)
            E[i][j] = D[i + 1][j + 1];
}

void Doit0(int i, int j, int S, int T) {
    if (F[i][j][S] == 0) return;

    F(p, 0, 12) {
        int up = min(p >> 1, 4);
        F(q, 0, up)
            add(F[i + 1][j + p - q][T], 1LL * F[i][j][S] * E[4][q] * E[12 - q * 2][p - 2 * q]);
    }
}

void Doit1(int i, int j, int S, int T) {
    if (F[i][j][S] == 0) return;

    F(p, 0, 9) {
        int up = min(p >> 1, 2);
        F(q, 0, up)
            add(F[i + 1][j + p - q][T], 1LL * F[i][j][S] * E[2][q] * E[9 - q * 2][p - q * 2]);
    }
}

void Doit2(int i, int j, int S, int T, int S1, int S2) {
    if (F[i][j][S] == 0) return;

    // Not Add S1 or S2
    F(p, 0, 9) {
        int up = min(p >> 1, 2);
        F(q, 0, up) {
            add(F[i + 1][j + p - q][S1], 1LL * F[i][j][S] * E[2][q] * E[9 - q * 2][p - q * 2]);
            add(F[i + 1][j + p - q][S2], 1LL * F[i][j][S] * E[2][q] * E[9 - q * 2][p - q * 2]);
        }
    }

    // Add both
    int yes = (T % 3 == 0);
    F(p, 0, 6)
        F(q, 0, min(p >> 1, yes))
            add(F[i + 1][j + p - q][T], 1LL * F[i][j][S] * E[6 - q * 2][p - q * 2]);
    
    if (yes) {
        F(p, 0, 6)
            F(q, 0, min(p >> 1, 1))
                add(F[i + 1][j + p - q - 1][0], 1LL * F[i][j][S]  * E[6 - q * 2][p - q * 2]);
    }
}

void Doit3(int i, int j, int S, int T, int S1, int S2, int S3) {
    if (F[i][j][S] == 0) return;

    // Only Add one
    F(p, 0, 9)
        F(q, 0, min(p >> 1, 2)) {
            int t = q * 2;
            add(F[i + 1][j + p - q][S1], 1LL * F[i][j][S] * E[2][q] * E[9 - t][p - t]);
            add(F[i + 1][j + p - q][S2], 1LL * F[i][j][S] * E[2][q] * E[9 - t][p - t]);
            add(F[i + 1][j + p - q][S3], 1LL * F[i][j][S] * E[2][q] * E[9 - t][p - t]);
        }

    // Add two
    F(p, 0, 6)
        F(q, 0, min(p >> 1, 1)) {
            int t = q * 2;
            add(F[i + 1][j + p - q][S - S1], 1LL * F[i][j][S] * E[6 - t][p - t]);
            add(F[i + 1][j + p - q][S - S3], 1LL * F[i][j][S] * E[6 - t][p - t]);
        }
    F(p, 0, 6)
        F(q, 0, min(p >> 1, 0)) 
            add(F[i + 1][j + p - q][S - S2], 1LL * F[i][j][S] * E[6 - q * 2][p - q *2]);

    // Add all
    F(p, 0, 3)
        F(q, 0, min(p >> 1, 0))
            add(F[i + 1][j + p - q][T], 1LL * F[i][j][S] * E[3 - q * 2][p - q * 2]);

    // Only add one but the others are together
    F(p, 0, 3)
        F(q, 0, min(p >> 1, 0)) {
            add(F[i + 1][j - 1 + p - q][S3], 1LL * F[i][j][S] * E[3 - q * 2][p - q * 2]);
            add(F[i + 1][j - 1 + p - q][S1], 1LL * F[i][j][S] * E[3 - q * 2][p - q * 2]);
        }
    
    // Add no one but two are together
    F(p, 0, 6)
        F(q, 0, min(p >> 1, 1))
            add(F[i + 1][j - 1 + p - q][T - S1 - S2 - S3], 2LL * F[i][j][S] * E[6 - q * 2][p - q * 2]);
}

void Doit4(int i, int j, int S, int S1, int S2, int S3, int S4) {
    if (F[i][j][S] == 0) return;
    
    // Not Add three
    Doit1(i, j, S, S - 14);
    Doit1(i, j, S, S - 13);
    Doit1(i, j, S, S - 11);
    Doit1(i, j, S, S - 7);

    // Not Add two
    F(p, 0, 6)
        F(q, 0, min(p >> 1, 1)) {
            int t = q * 2;
            add(F[i + 1][j + p - q][S - S1 - S2], 1LL * F[i][j][S] * E[6 - t][p - t]);
            add(F[i + 1][j + p - q][S - S2 - S3], 1LL * F[i][j][S] * E[6 - t][p - t]);
            add(F[i + 1][j + p - q][S - S3 - S4], 1LL * F[i][j][S] * E[6 - t][p - t]);
            add(F[i + 1][j + p - q][S - S4 - S1], 1LL * F[i][j][S] * E[6 - t][p - t]);
        }
    F(p, 0, 6)
        F(q, 0, min(p >> 1, 0)) {
            int t = q * 2;
            add(F[i + 1][j + p - q][S - S1 - S3], 1LL * F[i][j][S] * E[6 - t][p - t]);
            add(F[i + 1][j + p - q][S - S2 - S4], 1LL * F[i][j][S] * E[6 - t][p - t]);
        }
    
    // Not Add only one
    
    F(p, 0, 3)
        F(q, 0, min(p >> 1, 0)) {
            int t = q * 2;
            add(F[i + 1][j + p - q][S - S1], 1LL * F[i][j][S] * E[3 - t][p - t]);
            add(F[i + 1][j + p - q][S - S2], 1LL * F[i][j][S] * E[3 - t][p - t]);
            add(F[i + 1][j + p - q][S - S3], 1LL * F[i][j][S] * E[3 - t][p - t]);
            add(F[i + 1][j + p - q][S - S4], 1LL * F[i][j][S] * E[3 - t][p - t]);
        }
    
    // Add all of them
    add(F[i + 1][j][S], F[i][j][S]);
    
    // Add both of them be together
    add(F[i + 1][j - 1][S - S1 - S2], F[i][j][S]);
    add(F[i + 1][j - 1][S - S2 - S3], F[i][j][S]);
    add(F[i + 1][j - 1][S - S3 - S4], F[i][j][S]);
    add(F[i + 1][j - 1][S - S4 - S1], F[i][j][S]);
    
    // Add all of them be together // have 2 possible
    add(F[i + 1][j - 2][0], F[i][j][S] * 2LL);
    
    // Add both of them be together and have two possible
    
    // possible 1
    F(p, 0, 6)
        F(q, 0, min(p >> 1, 1))
            add(F[i + 1][j + p - q - 1][0],  4LL * F[i][j][S] * E[6 - q * 2][p - q * 2]);
    // possible 2
    F(p, 0, 3)
        F(q, 0, min(p >> 1, 0)) {
            int t = 2 * q;
            add(F[i + 1][j + p - q - 1][S1], 2LL * F[i][j][S] * E[3 - t][p - t]);
            add(F[i + 1][j + p - q - 1][S2], 2LL * F[i][j][S] * E[3 - t][p - t]);
            add(F[i + 1][j + p - q - 1][S3], 2LL * F[i][j][S] * E[3 - t][p - t]);
            add(F[i + 1][j + p - q - 1][S4], 2LL * F[i][j][S] * E[3 - t][p - t]);
        }
}

void FindTheAns() {
    F(i, 0, n - 1)
        F(j, 0, k + 2) {
            // S = 0;
            F(p, 0, 15)
                Doit0(i, j, p, 0);



            // S = 1, 2, 4, 8
            Doit1(i, j, 1, 1);
            Doit1(i, j, 2, 2);
            Doit1(i, j, 4, 4);
            Doit1(i, j, 8, 8);



            // S = 3, 6, 9, 12
            Doit2(i, j, 3, 3, 1, 2);
            Doit2(i, j, 6, 6, 2, 4);
            Doit2(i, j, 12, 12, 4, 8);
            Doit2(i, j, 9, 9, 1, 8);
            // S = 5, 10
            Doit2(i, j, 10, 10, 2, 8);
            Doit2(i, j, 5, 5, 1, 4);



            // S = 7, 11, 13, 14
            Doit3(i, j, 7, 7, 1, 2, 4);
            Doit3(i, j, 14, 14, 2, 4, 8);
            Doit3(i, j, 13, 13, 4, 8, 1);
            Doit3(i, j, 11, 11, 8, 1, 2);



            // S = 15
            Doit4(i, j, 15, 1, 2, 4, 8);
        }
}

void SolveAns() {
    int tot = 1, ans = 0;
    F(i, 1, k)
        tot = (1LL * tot * i) % Mo;

    F(S, 0, 15)
        add(ans, 1LL * F[n][k][S] * tot % Mo);

    printf("%d\n", ans);
}

int main() {
    freopen("magic.in", "r", stdin);
    freopen("magic.out", "w", stdout);
    
    Init();
    
    GetMul();
    
    FindTheAns();

    SolveAns();
    
    return 0;
}

转载于:https://www.cnblogs.com/Pro-king/p/9391851.html

内容概要:本文系统研究了在有限控制集约束下,三相并网逆变器中电流与功率双模态模型预测控制(MPC)的等效机理及其性能边界。通过构建精确的预测模型,设计合理的代价函数,并结合Simulink仿真与Matlab代码实现,深入分析了电流预测控制与功率预测控制两种策略在动态响应速度、稳态精度、谐波抑制能力和抗扰性等方面的差异与内在联系。研究揭示了在特定系统参数和运行条件下,两种控制模式之间的等效转化机制,并界定了各自的适用范围与性能极限。同时,探讨了多模态控制的切换逻辑、实时性优化及预测模型不确定性对控制性能的影响,旨在提升逆变器在复杂电网环境下的综合控制品质与鲁棒性。; 适合人群:具备电力电子、自动控制或新能源并网等相关专业背景,熟悉Matlab/Simulink仿真环境,从事研究生及以上层次科研或从事高端电力电子装备研发的工程技术人员。; 使用场景及目标:①深入理解模型预测控制在并网逆变器中的具体实现方法与理论基础;②掌握电流与功率双模态MPC控制器的设计、仿真建模与性能对比评估流程;③为高动态、高精度并网控制系统的方案选型、参数优化与工程化应用提供坚实的理论依据和技术参考。; 阅读建议:建议结合所提供的Simulink仿真模型与Matlab源代码进行同步实验验证,重点关注预测模型的建立过程、控制律的数学推导以及不同工况下的仿真结果对比分析,宜配合现代控制理论、电力电子变换技术及并网标准等相关资料进行系统性学习。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值