CCF201409-5 拼图(30分)

试题编号: 201409-5
试题名称: 拼图
时间限制: 3.0s
内存限制: 256.0MB
问题描述:
问题描述
给出一个n×m的方格图,现在要用如下L型的积木拼到这个图中,使得方格图正好被拼满,请问总共有多少种拼法。其中,方格图的每一个方格正好能放积木中的一块。积木可以任意旋转。

输入格式
输入的第一行包含两个整数n, m,表示方格图的大小。
输出格式
输出一行,表示可以放的方案数,由于方案数可能很多,所以请输出方案数除以1,000,000,007的余数。
样例输入
6 2
样例输出
4
样例说明
四种拼法如下图所示:

评测用例规模与约定
在评测时将使用10个评测用例对你的程序进行评测。
  评测用例1和2满足:1<=n<=30,m=2。
  评测用例3和4满足:1<=n, m<=6。
  评测用例5满足:1<=n<=100,1<=m<=6。
  评测用例6和7满足:1<=n<=1000,1<=m<=6。
  评测用例8、9和10满足:1<=n<=10^15,1<=m<=7。

问题链接:CCF201409试题。

问题描述:(参见上文)

问题分析:也许从数学上先推演一下比较好,这有点难。

看似可以用递归函数来实现,实际做起来没有那么容易。只得了30分,有胜于无而已。

对于输入的n和m,若n*m不是3的倍数,则肯定无法完全覆盖。同时,如果不是6的倍数则不能完全覆盖。

n和m哪个更大是不知道的,假设n<=m的情况下进行计算即可,若n>m将n和m交换即可。题意中则相反,是m<=n,实际上是一样的。

以下给出若各种拼图组合,可以在其基础上找出递归函数关系:

 

  

 


程序说明:程序有待改进,或者需要新的思路。

提交后得30分的C++语言程序如下:

/* CCF201409-5 拼图 */#include <iostream>using namespace std;const long long MOD = 1000000007;// 模幂计算函数
inline long long powermod(int x, int y, long long mod)
{long long ans = 1;while(y) {if(y & 1) {ans *= x;ans %= mod;}x *= x;x %= mod;y >>= 1;}return ans;
}long long puzzle(int n, int m)
{long long b1, b2;if(n <= 1 || m <= 1)return 0;// 面积不是3的倍数则不可能if((n * m) % 3 != 0)return 0;// 让n<=mif(n > m) {int temp = n;n = m;m = temp;}if(n == 2) {   // 2 * 3 * k, k = m / 3// n=2时,m必须是3的倍数if(m % 3 != 0)return 0;return powermod(2, m / 3, MOD);} else if(n == 3) { // 3 * 2 * k, k = m / 2// n=3时,m必须是2的倍数if(m % 2 != 0)return 0;return powermod(2, m / 2, MOD);} else if(n == 4 && m == 6) { // 4 * 6b1 = puzzle(2, m);  // 分为两半b2 = puzzle(2, 3);   // 4*6异形数量return (b1 * b1 + b2) % MOD;} else if(n == 4) { // 4 * 3 * 2 * k, k = m / 6 或 4 * 3 * 2 * k + 4 * 3, k = m / 6b1 = powermod(puzzle(4, 6), m / 6, MOD);if(m % 6 == 0) {return b1;} else if(m % 6 == 3) {// 除了组合,还需要考虑排列b2 = puzzle(3, 4);return b1 * b2 * (m / 6 + 1) % MOD;} elsereturn 0;} else if(n == 5 && m == 6) {long long b1, b2;b1 = puzzle(3, m);b2 = puzzle(2, m);return b1 * b2 * 2 % MOD;   // 64} else if(n == 5) {if(m % 6 != 0)return 0;return powermod(puzzle(5, 6), m / 6, MOD);} else if(n == 6 && m == 6) {// 上下分,左右分,4*6异形与2*6拼接,6*6异形(2种)b1 = puzzle(3, m);  // 上下分,或左右分b2 = puzzle(2, 3);   // 4*6异形数量return (b1 * b2 * 2 + b2 * puzzle(2, 6) * 4 + 2) % MOD;} else if(n == 6) {// 6*6不正确,这个计算就没有意义了return 0;} else {// 其他情况:不考虑return 0;}
}int main()
{int n, m;long long ans;cin >> n >> m;ans = puzzle(n, m);cout << ans << endl;return 0;
}

改进:上述程序提交后只得30分,所以进行了进一步的分析与改进:

1.使得方格图正好被拼满,需要m*n是6的倍数,因为积木块面积为3。程序中35-37行代码改为:

    // 方格图被完全拼满,面积不是6的倍数则不可能if((n * m) % 6 != 0)return 0;

2.根据题意,m最大为7,即只需要考虑m=2,3,4,5,6,7的情况。这也是得100分的希望所在。

所以,程序中只需要考虑n=2,3,4,5,6,7的情况(程序中,与题意相比,n和m互换)。

3.程序中增加n=7的代码,需要考虑6*7和7*m的情况。对于6*7的方格图,可以由6*2和6*5的方格图组成,也可以由6*3和6*4的方格图组成。

改进后提交得30分的C++语言程序如下:

/* CCF201409-5 拼图 */#include <iostream>using namespace std;const long long MOD = 1000000007;// 模幂计算函数
inline long long powermod(int x, int y, long long mod)
{long long ans = 1;while(y) {if(y & 1) {ans *= x;ans %= mod;}x *= x;x %= mod;y >>= 1;}return ans;
}long long puzzle(int n, int m)
{long long b1, b2;if(n <= 1 || m <= 1)return 0;// 方格图被完全拼满,面积不是6的倍数则不可能if((n * m) % 6 != 0)return 0;// 让n<=mif(n > m) {int temp = n;n = m;m = temp;}if(n == 2) {   // 2 * 3 * k, k = m / 3// n=2时,m必须是3的倍数if(m % 3 != 0)return 0;return powermod(2, m / 3, MOD);} else if(n == 3) { // 3 * 2 * k, k = m / 2// n=3时,m必须是2的倍数if(m % 2 != 0)return 0;return powermod(2, m / 2, MOD);} else if(n == 4 && m == 6) { // 4 * 6b1 = puzzle(2, m);  // 分为两半b2 = puzzle(2, 3);   // 4*6异形数量return (b1 * b1 + b2) % MOD;} else if(n == 4) { // 4 * 3 * 2 * k, k = m / 6 或 4 * 3 * 2 * k + 4 * 3, k = m / 6b1 = powermod(puzzle(4, 6), m / 6, MOD);if(m % 6 == 0) {return b1;} else if(m % 6 == 3) {// 除了组合,还需要考虑排列b2 = puzzle(3, 4);return b1 * b2 * (m / 6 + 1) % MOD;} elsereturn 0;} else if(n == 5 && m == 6) {long long b1, b2;b1 = puzzle(3, m);b2 = puzzle(2, m);return b1 * b2 * 2 % MOD;   // 64} else if(n == 5) {if(m % 6 != 0)return 0;return powermod(puzzle(5, 6), m / 6, MOD);} else if(n == 6 && m == 6) {// 上下分,左右分,4*6异形与2*6拼接,6*6异形(2种)b1 = puzzle(3, m);  // 上下分,或左右分b2 = puzzle(2, 3);   // 4*6异形数量return (b1 * b2 * 2 + b2 * puzzle(2, 6) * 4 + 2) % MOD;} else if(n == 6 && m == 7) {b1 = puzzle(2, 6) * puzzle(5, 6);b2 = puzzle(3, 6) * puzzle(4, 6);return (b1 + b2) % MOD;} else if(n == 6) {// 6*6不正确,这个计算就没有意义了return 0;} else if(n == 7) {return powermod(puzzle(6, 7), m / 6, MOD);} else {// 其他情况:不考虑return 0;}
}int main()
{int n, m;long long ans;cin >> n >> m;ans = puzzle(n, m);cout << ans << endl;return 0;
}

经过改进的程序仍然的30分,增加的有关7*m的代码完全不得分。

由于6*7的方格图,可以由6*2和6*5的方格图组成,也可以由6*3和6*4的方格图组成,那应该是以下几种方格图的组合数计算有错误:

6*2

6*5

6*3

6*4

经过仔细考察和梳理,终于发现4*6至少漏算了一个情况,至少应该如下图所示:



上述程序的56-50行改为(异形数量*2):

    } else if(n == 4 && m == 6) { // 4 * 6b1 = puzzle(2, m);      // 分为两半b2 = puzzle(2, 3) * 2;   // 4*6异形数量return (b1 * b1 + b2) % MOD;

改进后提交只得20分,分数更少了,怀疑测试数据有BUG。

下一步只能考虑先改进6*6的情形了。




 











转载于:https://www.cnblogs.com/tigerisland/p/7564111.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259541.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ 0x

转载于:https://www.cnblogs.com/iiiDragon/p/3230006.html

Github for Windows使用介绍

Git已经变得非常流行&#xff0c;连Codeplex现在也已经主推Git。Github上更是充斥着各种高质量的开源项目&#xff0c;比如ruby on rails&#xff0c;cocos2d等等。对于习惯Windows图形界面的程序员来讲&#xff0c;Github的使用是需要点时间和耐心的&#xff0c;然而最近Githu…

matlab中udt函数,《MATLAB信号处理超级学习手册》——2.5 离散时间信号中的运算...

本节书摘来自异步社区《MATLAB信号处理超级学习手册》一书中的第2章&#xff0c;第2.5节&#xff0c;作者&#xff1a;MATLAB技术联盟 , 史洁玉著&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看2.5 离散时间信号中的运算MATLAB信号处理超级学习手册2.5.1 离散…

构建Docker镜像(三)

作者:李晓辉联系方式:Xiaohui_lifoxmail.comQQ:939958092一、建立Dockerfile1、准备文件新建一个目录和一个 Dockerfilemkdir /steventouch /steven/Dockerfile2、更新Dockerfile这个步骤是在设计镜像&#xff0c;如果你需要在镜像内包含什么软件&#xff0c;将来开放哪些端口&…

你必须很努力,才能看上去毫不费力

世上没有一件工作不辛苦&#xff0c;没有一处人事不复杂。 从今天起&#xff0c;每天微笑吧&#xff0c; 世上除了生死&#xff0c;都是小事。 不管遇到了什么烦心事&#xff0c;都不要自己为难自己&#xff1b; 无论今天发生多么糟糕的事&#xff0c;都不应该感到悲伤。 今天是…

HDU 4631 Sad Love Story 平面内最近点对

http://acm.hdu.edu.cn/showproblem.php?pid4631 题意: 在平面内依次加点,求每次加点后最近点对距离平方的和 因为是找平面最近点对...所以加点以后这个最短距离一定是递减的...所以最后会形成这样一个函数图像 所以我们只要从后往前依次删点即可... 15秒惊险水过...不过我最小…

itoa的用法

功能&#xff1a;将任意类型的整数转换为字符串。在<stdlib.h>中与之有相反功能的函数是atoi。 用法&#xff1a;char*itoa(int value,char*string,int radix); int value 被转换的整数&#xff0c;char *string 转换后储存的字符数组&#xff0c;int radix 转换进制数…

Tomcat与Gzip与缓存

国内私募机构九鼎控股打造APP&#xff0c;来就送 20元现金领取地址&#xff1a;http://jdb.jiudingcapital.com/phone.html内部邀请码&#xff1a;C8E245J &#xff08;不写邀请码&#xff0c;没有现金送&#xff09;国内私募机构九鼎控股打造&#xff0c;九鼎投资是在全国股份…

java竖向菜单,垂直滑动菜单

www.lanrentuku.comtd {font-size: 12px;}width"200" />height9 src"images/bit05.gif" width8alignabsMiddle> href"javascript:void(null)">文管产品 src"images/bit06.gif" width8 alignabsMiddle> href"http://w…

[转]第一章 Windows Shell是什么 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987862】...

一个操作系统外壳的不错的定义是它是一个系统提供的用户界面&#xff0c;它允许用户执行公共的任务&#xff0c;如访问文件系统&#xff0c;导出执行程序&#xff0c;改变系统设置等。MS-DOS有一个Command.COM扮演着这个角色。然而Windows已经有了图形界面环境&#xff0c;他的…

20155222卢梓杰 《Java程序设计》第1周学习总结

20155222 《Java程序设计》第1周学习总结 教材学习内容总结 JDK是一个工具程序&#xff0c;包括了JAVA程序语言&#xff0c;工具程序与JRE&#xff0c;JRE包括了部署技术&#xff0c;JAVA SE API 与 JVM。 教材学习中的问题和解决过程 第一章&#xff1a;JDK的变量和选项如何设…

DateTime.Now.ToString() 用法

//2008年4月24日 System.DateTime.Now.ToString("D"); //2008-4-24 System.DateTime.Now.ToString("d"); //2008年4月24日 16:30:15 System.DateTime.Now.ToString("F"); //2008年4月24日 16:30 System.DateTime.No…

GAP平台

2019独角兽企业重金招聘Python工程师标准>>> 转载于:https://my.oschina.net/u/2441327/blog/846754

二进制与十进制的转换

本文参考:http://www.360doc.com/content/11/0308/14/5327079_99222581.shtml文献整理所得。 1.正整数的十进制转换为二进制. 十进制整数转换为二进制整数采用"除2取余&#xff0c;逆序排列"法。具体做法是&#xff1a;用2整除十进制整数&#xff0c;可以得到一个商…

php记录已经点击过,最近一次的PHP面试题记录,office已到手!

1、explain 具体哪些等级具体有 system、const、range、index、all2、MySQL 优化避免全表查询&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索引应尽量避免在 where 子句中对字段进行 null 值判断&#xff0c;否则将导致引擎放弃使用索引而进行全表扫描 (可以将字…

原生Ajax讲解

典型的http通信&#xff1a;浏览器向服务器发出请求&#xff0c;服务器向客户端返回响应&#xff0c;浏览器重新加载页面&#xff0c;这种不连续的页面加载方式导致用户的体验变得杂乱&#xff0c;缺乏连贯性。 如&#xff1a; 在一般的web应用程序中&#xff0c;用户填写表单字…

16、Python与设计模式--模板模式

一、股票查询客户端 投资股票是种常见的理财方式&#xff0c;我国股民越来越多&#xff0c;实时查询股票的需求也越来越大。今天&#xff0c;我们通过一个简单的股票查询客户端来认识一种简单的设计模式&#xff1a;模板模式。根据股票代码来查询股价分为如下几个步骤&#xff…

并行编程2——多核体系架构

1.1 多核处理器定义 多内核处理器架构是指&#xff1a;芯片设计工程师在单个处理器中集成两个或多个 “执行内核&#xff08;即计算引擎&#xff09;”。多内核处理器可直接插入到单一处理器基座中。但是&#xff0c;操作系统会把它的每个执行内核作为独立的逻辑处理器&#x…

[Node.js]get/post请求

摘要 在很多情况下&#xff0c;我们的web服务器都需要接受客户端浏览器传递的参数或者数据。最常见的是get和post请求。 获取get请求的内容 get请求传递的参数在url中&#xff0c;参数部分在?后面。因此可以手动解析后面的内容作为get请求的参数。node.js中url模块中的parse函…

MyEclipse10 Tomcat7 JDK1.7 配置

第一步.MyEclipse10 Tomcat7 JDK1.7下载 MyEclipse10http://downloads.myeclipseide.com/downloads/products/eworkbench/indigo/installers/myeclipse-10.0-offline-installer-windows.exe Tomcat http://tomcat.apache.org/ Java SE Development Kit 7 WINDOWS版 http://www…