2020 ICPC 南京 H Harmonious Rectangle (DFS剪枝+思维)
题目链接H-Harmonious Rectangle_第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京)
题目描述
For example, , and are harmonious, while is not (same number for same color, and different numbers for different colors).
For each point in , where is the set of all integers, Kotori wants to paint it into one of the three colors: red, blue, yellow. She wonders the number of different ways to color them so that there exists at least one harmonious rectangle formed by the points, whose edges are all parallel to the - or -axis. That is to say, there exists and such that
Two coloring plans are considered different if there exists a point having different colors in the two coloring plans.
输入描述:
There are multiple test cases. The first line of the input contains an integer () indicating the number of test cases. For each test case: The first and only line contains three integers , ().
输出描述:
For each test case output one line containing one integer indicating the number of different ways of coloring modulo .
输入
复制 3 1 4 2 2 3 3
3 1 4 2 2 3 3
输出
复制 0 15 16485
0 15 16485
题目大意
给你一个n*m的矩阵,每个点都可以取三种颜色。问你有多少种染色方法可以使得矩阵中至少一对(x1,y1)与(x2,y2)满足下列式子。
(a[y1][x1] == a[y2][x1] && a[y1][x2] == a[y2][x2]) ||
(a[y1][x1] == a[y1][x2] && a[y2][x1] == a[y2][x2]))
分析
考虑在矩阵中选择任意两行a和b
a1 a2 a3 a4 a5 a6 ......
b1 b2 b3 b4 b5 b6 ......
可知(a1,b1)有3*3=9种组合方式。根据鸽笼原理,或者直接动脑子想想,可以想到当列数>9时,一定存在另一组(ai,bi)与(a1,b1)相同。同理,当行数>9时,一定存在两组相同的列。所以可以分类讨论:
- if n=1 || m=1 ,必为0
- else if n>9 || m>9,结果为3n∗m3^{n*m}3n∗m
- else 在9*9范围内,可以DFS剪枝搜索,然后把结果打个表。
打表用代码
分别用DFS剪枝和暴力穷举法实现。后者用来与前者在小范围时对拍。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;ll mod_mul(ll a, ll b, ll n) {a %= n; //优化后只要在开头模一次,其他的地方用if,效率提升近一倍b %= n;ll res = 0;while (b) {if (b & 1) {res += a;if (res > n) res -= n;}a += a;if (a > n) a -= n;b /= 2; //没开o2的话要换成b>>=1}return res;
}ll mod_exp(ll a, ll b, ll n) {ll res = 1;a = a % n;while (b) {if (b & 1) res = mod_mul(res, a, n);a = mod_mul(a, a, n);b /= 2;}return res;
}const ll MOD = 1e9 + 7;
const int MAXN = 12;
int a[MAXN][MAXN];
int n, m;
long long gcnt;void get_next() {const static int base = 3;int carry = 1;for (int i = n - 1; i >= 0; i--) {for (int j = m - 1; j >= 0; j--) {a[i][j] += carry;carry = 0;if (a[i][j] >= base) {carry = a[i][j] / base;a[i][j] %= base;}}}
}void print() {for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {printf("%d ", a[i][j]);}printf("\n");}printf("\n");
}bool check() {for (int y1 = 0; y1 < n; y1++) {for (int x1 = 0; x1 < m; x1++) {for (int y2 = y1 + 1; y2 < n; y2++) {for (int x2 = x1 + 1; x2 < m; x2++) {if ((a[y1][x1] == a[y2][x1] && a[y1][x2] == a[y2][x2]) ||(a[y1][x1] == a[y1][x2] && a[y2][x1] == a[y2][x2]))return true;}}}}return false;
}void dfs(int xx, int yy) {for (int color = 0; color < 3; color++) {int x2 = xx;int y2 = yy;a[y2][x2] = color;bool flag = true;for (int y1 = 0; y1 < y2 && flag; y1++) {for (int x1 = 0; x1 < x2 && flag; x1++) {if ((a[y1][x1] == a[y2][x1] && a[y1][x2] == a[y2][x2]) ||(a[y1][x1] == a[y1][x2] && a[y2][x1] == a[y2][x2])) {flag = false;gcnt +=mod_exp(3LL, (1LL * (n - 1 - y2) * (m) + (m - 1) - x2), MOD);gcnt %= MOD;}}}if (flag) {x2++;if (x2 >= m) {x2 = 0;y2++;if (y2 >= n){continue;}}dfs(x2, y2);}}a[yy][xx]=-1;
}ll solve_dfs(){gcnt=0;dfs(0,0);return gcnt;
}int solve_exhaust() {int p = pow(3, n * m);int cnt = 0;for (int i = 0; i < p; i++) {if (check()) {cnt++;// print();}// print();get_next();}return cnt;
}int main() {for(n =1; n<=9;n++){for(m=1;m<=9;m++){if(m==1||n==1) printf("0, ");else{memset(a,0,sizeof(a));printf("%lld, ",solve_dfs());//printf("%lld, ",solve_exhaust());}}printf("\n");}return 0;}
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
int n,m;ll mod_mul(ll a, ll b, ll n) {a %= n; //优化后只要在开头模一次,其他的地方用if,效率提升近一倍b %= n;ll res = 0;while (b) {if (b & 1) {res += a;if (res > n) res -= n;}a += a;if (a > n) a -= n;b /= 2; //没开o2的话要换成b>>=1}return res;
}ll mod_exp(ll a, ll b, ll n) {ll res = 1;a = a % n;while (b) {if (b & 1) res = mod_mul(res, a, n);a = mod_mul(a, a, n);b /= 2;}return res;
}ll dat[9][9]={0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 15, 339, 4761, 52929, 517761, 4767849, 43046721, 387420489,
0, 339, 16485, 518265, 14321907, 387406809, 460338013, 429534507, 597431612,
0, 4761, 518265, 43022385, 486780060, 429534507, 792294829, 175880701, 246336683,
0, 52929, 14321907, 486780060, 288599194, 130653412, 748778899, 953271190, 644897553,
0, 517761, 387406809, 429534507, 130653412, 246336683, 579440654, 412233812, 518446848,
0, 4767849, 460338013, 792294829, 748778899, 579440654, 236701429, 666021604, 589237756,
0, 43046721, 429534507, 175880701, 953271190, 412233812, 666021604, 767713261, 966670169,
0, 387420489, 597431612, 246336683, 644897553, 518446848, 589237756, 966670169, 968803245};int main() {int T;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);if(n==1||m==1){printf("0\n");}else if(n<=9||m<=9){n--;m--;printf("%lld\n",dat[n][m]%MOD);}else{printf("%lld\n",mod_exp(3,1LL*n*m,MOD));}}return 0;
}
参考资料
2020年ICPC南京区域赛题解 - 知乎
2020 ICPC 南京 H Harmonious Rectangle (DFS剪枝+思维)相关推荐
- 2020 ICPC 南京站 M Monster Hunter (树形DP)
题目链接:M-Monster Hunter_第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京) 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5 ...
- 2020 ICPC 南京站 F Fireworks (概率论+三分)
题目链接:F-Fireworks_第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京) 题目描述 Kotori is practicing making fireworks for the ...
- 容斥 + 爆搜打表 ---- 2020年南京icpc H.Harmonious Rectangle
题目链接 题目大意: 就是给你一个二维平面{(x,y)∣1≤x≤n,1≤y≤m}\{(x,y)|1\leq x\leq n,1\leq y \leq m\}{(x,y)∣1≤x≤n,1≤y≤m},你现 ...
- 树形dp --- 2020 icpc 南京 M Monster Hunter
题目链接 题目大意: 解题思路: 首先我们分析一下每个点状态是怎么? 1.1: 对于这个点我们删除的代价我们要看一下它儿子有多少个没被删除(指没用)因为父亲节点没删这个点呀删除不了 1.2: 那么这个 ...
- Fireworks(2020 ICPC南京)
Fireworks 题意: 你每做一个烟花要n分钟,释放已做好的所有烟花需要m分钟,每只烟花成功释放的概率为p.问你在采取最优策略的前提下,直到成功释放第一个烟花时最小的期望时间花费. 题解: 最佳策 ...
- 组合计数 ---- 2020 icpc 上海 The Journey of Geor Autumn(思维划分问题计数+预处理优化)
题目链接 题目大意: 就是你有一个nnn的全排列,现在问你去重排这个排列使得对于给定的kkk,满足对于任意的ai,i>ka_i,i>kai,i>k的都有ai>min(ai−1 ...
- 2021 ICPC 南京 3.27训练赛
2021 ICPC 南京 D - Paimon Sorting J - Xingqiu's Joke I - Cloud Retainer's Game 题目链接 D - Paimon Sorting ...
- 2020 ICPC Macau A. Accelerator(期望,计数,分治FFT)(每日一题 21.7.6)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 2020 ICPC Macau A. Accelerator(分治FFT) Problem 给定长度为 ...
- POJ2688状态压缩(可以+DFS剪枝)
题意: 给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路: 水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...
最新文章
- PMCAFF微课堂 | 京东零售平台资深PM深度揭秘京东的订单体系
- Oracle中大批量删除数据的方法
- ❤️六W字《计算机基础知识》(一)(建议收藏)❤️
- codeforces 768 C. Jon Snow and his Favourite Number(思维+暴力)
- 算法分析-动态规划-01背包
- cartographer探秘之文章索引
- flash player 10 beta已经放出
- vue + echarts 实现以中国为中心的世界3D地图
- signature=99daf37ca32015c39987d04abe5a559d,合肥2015年7月4日至2015年7月16日交通违章查询...
- 慕课网C#开发轻松入门 6-1练习题目
- 上海交通大学计算机科学与技术招生网,上海交通大学计算机科学与技术研究生招生...
- android滑屏效果,Android使用ViewFlipper和GestrueDetector共同实现滑屏效果实例
- 利用ps生成闪电特效
- java多线程 isAlive方法的有趣现象
- 百度云盘下载jdk1.8
- Python函数部分2
- 【C语言进阶17——程序环境和预处理】
- 下载土豆视频——像个极客那样
- 无忧启动E源码 仿音速启动
- 【2016年总结】-- 你若盛开,清风自来