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.pswp.cn/news/259541.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259541.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259541.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

歐幾里得算法(即輾轉相除法)的時間復雜度

本文是參考新浪博客而寫。 歐幾里得算法, 又稱輾轉相除法, 用于求兩個自然數的最大公約數. 算法的思想很簡單, 基于下面的數論等式 gcd(a, b) gcd(b, a mod b) 其中gcd(a, b)表示a和b的最大公約數, mod是模運算, 即求a除以b的余數. 代碼如下: #include <iostream> #i…

UIImageJPEGRepresentation和UIImagePNGRepresentation

在Iphone上有兩種讀取圖片數據的簡單方法: UIImageJPEGRepresentation和UIImagePNGRepresentation. UIImageJPEGRepresentation函數需要兩個參數:圖片的引用和壓縮系數.而UIImagePNGRepresentation只需要圖片引用作為參數.通過在實際使用過程中,比較發現: UIImagePNGRepresenta…

C++ 0x

轉載于:https://www.cnblogs.com/iiiDragon/p/3230006.html

系列文章----.Net程序員學用Oracle系列

.Net程序員學用Oracle系列(18)&#xff1a;PLSQL Developer 攻略.Net程序員學用Oracle系列(17)&#xff1a;數據庫管理工具(SQL Plus).Net程序員學用Oracle系列(16)&#xff1a;訪問數據庫(ODP.NET).Net程序員學用Oracle系列(15)&#xff1a;DUAL、ROWID、NULL.Net程序員學用Or…

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 離散…

iOS 將16進制顏色轉換成UIColor

很多地方我們都使用16進制顏色&#xff0c;但iPhone使用的是UIColor對象&#xff0c;不直接支持16進制顏色&#xff0c;為此&#xff0c;需要我們手動將16進制顏色轉換為UIColor - (UIColor *) hexStringToColor: (NSString *) stringToConvert {NSString *cString [[stringTo…

OBJ 文件格式

OBJ文件是一種標準的3D模型文件格式&#xff0c;很適合用于3D軟件模型之間的互導。比如在3dsMax或LightWave中建了一個模型&#xff0c;想把它調到Maya里面渲染或動畫&#xff0c;導出OBJ文件就是一種很好的選擇。目前幾乎所有知名的3D軟件都支持OBJ文件的讀寫&#xff0c;不過…

構建Docker鏡像(三)

作者:李曉輝聯系方式:Xiaohui_lifoxmail.comQQ:939958092一、建立Dockerfile1、準備文件新建一個目錄和一個 Dockerfilemkdir /steventouch /steven/Dockerfile2、更新Dockerfile這個步驟是在設計鏡像&#xff0c;如果你需要在鏡像內包含什么軟件&#xff0c;將來開放哪些端口&…

centos 配置php開發環境變量配置,CentOS中配置PHP和Nginx環境變量

搜索熱詞一、摘要在Linux CentOS系統上 安裝完PHP和Nginx后&#xff0c;一般需要執行查看版本命令’PHP -v’和’Nginx -v’,確認是否安裝成功,如果在沒有添加到環境變量之前&#xff0c;執行“PHP -v”命令查看當前PHP版本信息時&#xff0c;則會提示命令不存在的錯誤&#xf…

你必須很努力,才能看上去毫不費力

世上沒有一件工作不辛苦&#xff0c;沒有一處人事不復雜。 從今天起&#xff0c;每天微笑吧&#xff0c; 世上除了生死&#xff0c;都是小事。 不管遇到了什么煩心事&#xff0c;都不要自己為難自己&#xff1b; 無論今天發生多么糟糕的事&#xff0c;都不應該感到悲傷。 今天是…

HDU 4631 Sad Love Story 平面內最近點對

http://acm.hdu.edu.cn/showproblem.php?pid4631 題意: 在平面內依次加點,求每次加點后最近點對距離平方的和 因為是找平面最近點對...所以加點以后這個最短距離一定是遞減的...所以最后會形成這樣一個函數圖像 所以我們只要從后往前依次刪點即可... 15秒驚險水過...不過我最小…

c++三/五法則

如果這個類需要一個析構函數&#xff0c;我們幾乎可以肯定它也需要一個拷貝構造函數和一個拷貝賦值運算符。 如果一個類需要拷貝構造函數&#xff0c;幾乎可以肯定它也需要一個拷貝賦值運算符&#xff0c;反之亦然。 然而&#xff0c;無論是需要拷貝構造函數還是需要拷貝賦值運…

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…

作為IT從業者,你是如何做好個人職業規劃?

前言 寫這篇文章的原因是因為你前端時間看到朋友在公眾號&#xff08;Marno&#xff09;發的一篇文章《27歲程序員職業生涯的“中年危機”》有感而發&#xff0c;談談自己對IT從業人員的一些職業規劃上的想法。本篇文章是我在坐地鐵的時候在手機上碼出來的&#xff0c;寫的不好…

將一句話的單詞進行倒置,標點符號不倒換。比如一句話:“i love you.”倒換后變為you. love i

#include <string.h> #include <stdio.h> #include <stdlib.h>//將一句話的單詞進行倒置&#xff0c;標點符號不倒換。比如一句話:“i love you.”倒換后變為"you. love i" void reverse(char *str) {int i0,jstrlen(str)-1;int begin,end;char te…

JS一些實用的方法

1、首次為變量賦值時務必使用var關鍵字變量沒有聲明而直接賦值得話&#xff0c;默認會作為一個新的全局變量&#xff0c;要盡量避免使用全局變量。2、使用取代和!操作符會在需要的情況下自動轉換數據類型。但和!不會&#xff0c;它們會同時比較值和數據類型&#xff0c;這也使得…

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

一個操作系統外殼的不錯的定義是它是一個系統提供的用戶界面&#xff0c;它允許用戶執行公共的任務&#xff0c;如訪問文件系統&#xff0c;導出執行程序&#xff0c;改變系統設置等。MS-DOS有一個Command.COM扮演著這個角色。然而Windows已經有了圖形界面環境&#xff0c;他的…