• 题意不说

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

  • 这是我人生中做的最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;
}

[jzoj]4271. 【NOIP2015模拟10.27】魔法阵(37种转移的dp)的更多相关文章

  1. JZOJ 4269. 【NOIP2015模拟10.27】挑竹签

    4269. [NOIP2015模拟10.27]挑竹签 (File IO): input:mikado.in output:mikado.out Time Limits: 1000 ms  Memory ...

  2. [NOIP2015模拟10.27] [JZOJ4270] 魔道研究 解题报告(动态开点+权值线段树上二分)

    Description “我希望能使用更多的魔法.不对,是预定能使用啦.最终我要被大家称呼为大魔法使.为此我决定不惜一切努力.”——<The Grimoire of Marisa>雾雨魔理 ...

  3. [NOIP2015模拟10.27] 挑竹签 解题报告(拓扑排序)

    Description 挑竹签——小时候的游戏夏夜,早苗和诹访子在月光下玩起了挑竹签这一经典的游戏.挑竹签,就是在桌上摆上一把竹签,每次从最上层挑走一根竹签.如果动了其他的竹签,就要换对手来挑.在所有 ...

  4. [JZOJ 5911] [NOIP2018模拟10.18] Travel 解题报告 (期望+树形DP)

    题目链接: http://172.16.0.132/senior/#contest/show/2530/1 题目: EZ同学家里非常富有,但又极其的谦虚,说话又好听,是个不可多得的人才.        ...

  5. JZOJ 4273. 【NOIP2015模拟10.28B组】圣章-精灵使的魔法语

    4273. [NOIP2015模拟10.28B组]圣章-精灵使的魔法语 (File IO): input:elf.in output:elf.out Time Limits: 1000 ms  Mem ...

  6. JZOJ 4272. 【NOIP2015模拟10.28B组】序章-弗兰德的秘密

    272. [NOIP2015模拟10.28B组]序章-弗兰德的秘密 (File IO): input:frand.in output:frand.out Time Limits: 1000 ms  M ...

  7. [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)

    题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...

  8. [JZOJ 5893] [NOIP2018模拟10.4] 括号序列 解题报告 (Hash+栈+map)

    题目链接: https://jzoj.net/senior/#main/show/5893 题目: 题解: 考虑暴力怎么做,我们枚举左端点,维护一个栈,依次加入元素,与栈顶元素和栈内第二个元素相同时弹 ...

  9. [JZOJ 5912] [NOIP2018模拟10.18] VanUSee 解题报告 (KMP+博弈)

    题目链接: https://jzoj.net/senior/#contest/show/2530/2 题目: 众所周知,cqf童鞋对哲学有着深入的理解和认识,并常常将哲学思想应用在实际生活中,例如锻炼 ...

随机推荐

  1. Python装饰器、内置函数之金兰契友

    装饰器:装饰器的实质就是一个闭包,而闭包又是嵌套函数的一种.所以也可以理解装饰器是一种特殊的函数.因为程序一般都遵守开放封闭原则,软件在设计初期不可能把所有情况都想到,所以一般软件都支持功能上的扩展, ...

  2. LeetCode算法题-Shortest Unsorted Continuous Subarray(Java实现)

    这是悦乐书的第267次更新,第281篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第134题(顺位题号是581).给定一个整数数组,找到一个连续的子数组,按升序对该子数组 ...

  3. docker容器日志收集方案汇总评价总结

    docker日志收集方案有太多,下面截图罗列docker官方给的日志收集方案(详细请转docker官方文档).很多方案都不适合我们下面的系列文章没有说. 经过以下5篇博客的叙述简单说下docker容器 ...

  4. 2016 西普杯丶天津CTF预选赛(3/6)

    哆啦A梦(图片隐写) 格式:SimCTF{ } 解:放到kail中binwalk一下(Binwalk是一个固件的分析工具,旨在协助研究人员对固件非分析,提取及逆向工程用处.简单易用,完全自动化脚本,并 ...

  5. C#基础知识之字符串比较方法:“==”操作符;RefernceEquals;String.Equals方法;String.Compare方法;String.CompareOrdinal方法。

    一.“==”操作符:String.Equals:ReferenceEquals 方法 1.在编程中实际上我们只需要这两种比较,c#中类型也就这两种 (1)值类型的比较:一般我们就是判断两个值类型实例各 ...

  6. 好程序员技术教程分享JavaScript运动框架

    好程序员技术教程分享JavaScript运动框架,有需要的朋友可以参考下. JavaScript的运动,即让某元素的某些属性由一个值变到另一个值的过程.如让div的width属性由200px变到400 ...

  7. MicroPython实例之TPYBoard开发板控制OLED显示中文

    0x00 前言 之前看到一篇文章是关于TPYBoard v102控制OLED屏显示的,看到之后就想尝试一下使用OLED屏来显示中文.最近利用空余时间搞定了这个实验,特此将实验过程及源码分享出来,方便以 ...

  8. Winform让扫描枪听话,防止在有焦点的地方就扫码输入的尴尬

    关注点: 1.扫描枪在扫描到条码后会在有焦点的地方显示扫描到的条码并且可设置扫码后添加回车换行让我很尴尬 2.怎样拦截扫码输入,扫描到条码就自动会嘀一声.不要这么智能行不行.瞎BB 需求详解 公司生产 ...

  9. OCR技术浅析-自写篇(2)

    本例仅以本人浅薄理解,妄想自制文字识别程序,实际在识别部分未有完善. <?php class readChar{ private $imgSize; //图片尺寸 private $imgGd2 ...

  10. AtCoDeerくんと選挙速報 / AtCoDeer and Election Report AtCoder - 2140 (按比例扩大)

    Problem Statement AtCoDeer the deer is seeing a quick report of election results on TV. Two candidat ...