Blocks
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3997   Accepted: 1775

Description

Panda has received an assignment of painting a line of blocks. Since Panda is such an intelligent boy, he starts to think of a math problem of painting. Suppose there are N blocks in a line and each block can be paint red, blue, green or yellow. For some
myterious reasons, Panda want both the number of red blocks and green blocks to be even numbers. Under such conditions, Panda wants to know the number of different ways to paint these blocks.

Input

The first line of the input contains an integer T(1≤T≤100), the number of test cases. Each of the next T lines contains an integer N(1≤N≤10^9) indicating the number of blocks.

Output

For each test cases, output the number of ways to paint the blocks in a single line. Since the answer may be quite large, you have to module it by 10007.

Sample Input

2
1
2

Sample Output

2
6

Source


题目大意:
有一排砖。数量为N。现要将砖所有染上色。有红、蓝、绿、黄四种颜色。

要求被染成红色和绿色的砖块数量必须为偶数,问一共同拥有多少种染色方案。(因为答案较大。模10007)


解题思路:
这道题有两种思路,一个是採用dp的思想,然后转化为矩阵。

还有一个是组合数学的思想。

dp:
用dp[N][4]来表示N块砖块的染色情况,一共同拥有四种状态。
1. dp[N][0] :表示N块中红色绿色的数量均为偶数。
2. dp[N][1] :表示N块中红色为偶数,绿色为奇数。
3. dp[N][2] :表示N块中红色为奇数,绿色为偶数。
4. dp[N][3]
:表示N块中红色绿色的数量均为奇数。
而状态转移方程为:
dp[N+1][0] = 2 * dp[N][0] + 1 * dp[N][1] + 1 * dp[N][2] + 0 * dp[N][3]
dp[N+1][1] = 1 * dp[N][0] + 2 * dp[N][1] + 0 * dp[N][2] + 1 * dp[N][3]
dp[N+1][2] = 1 * dp[N][0] + 0 * dp[N][1]
+ 2 * dp[N][2] + 1 * dp[N][3]
dp[N+1][3]
= 0 * dp[N][0] + 1 * dp[N][1] + 1 * dp[N][2] + 2 * dp[N][3]

上述的转移方程能够转化为矩阵:
|2 1 1 0|
|1 2 0 1|
|1 0 2 1|
|0 1 1 2|

代码:
/*
ID: wuqi9395@126.com
PROG:
LANG: C++
*/
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<fstream>
#include<cstring>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#define INF (1<<30)
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))
#define For(i, n) for (int i = 0; i < n; i++)
typedef long long ll;
using namespace std;
const int maxn = 5;
const int maxm = 5;
const int mod = 10007;
struct Matrix {
int n, m;
ll a[maxn][maxm];
void clear() {
n = m = 0;
memset(a, 0, sizeof(a));
}
Matrix operator * (const Matrix &b) const {
Matrix tmp;
tmp.clear();
tmp.n = n; tmp.m = b.m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
if (!a[i][j]) continue; //稀疏矩阵乘法优化
for (int k = 0; k < b.m; k++) {
tmp.a[i][k] += a[i][j] * b.a[j][k];
tmp.a[i][k] %= mod;
}
}
return tmp;
}
};
int n;
Matrix Matrix_pow(Matrix A, int k) {
Matrix res;
res.clear();
res.n = res.m = 4;
for (int i = 0; i < 4; i++) res.a[i][i] = 1;
while(k) {
if (k & 1) res = res * A;
k >>= 1;
A = A * A;
}
return res;
}
int main () {
int t;
scanf("%d", &t);
Matrix A;
A.clear();
A.n = A.m = 4;
A.a[0][0] = 2; A.a[0][1] = 1; A.a[0][2] = 1; A.a[0][3] = 0;
A.a[1][0] = 1; A.a[1][1] = 2; A.a[1][2] = 0; A.a[1][3] = 1;
A.a[2][0] = 1; A.a[2][1] = 0; A.a[2][2] = 2; A.a[2][3] = 1;
A.a[3][0] = 0; A.a[3][1] = 1; A.a[3][2] = 1; A.a[3][3] = 2;
while(t--) {
scanf("%d", &n);
Matrix res = Matrix_pow(A, n);
printf("%d\n", res.a[0][0]);
}
return 0;
}

组合数学:

假设没有限制,一共同拥有4 ^ n 次。如今考虑有 k 块被染为红色或绿色,且在k块中。一定有红色或绿色或两者均为奇数的情况。将这些情况减去,即是想要的答案。(1<= k <= n)
从n块中选择k块。为c(n, k)。 而从k块中选择不符合的情况染色,须要对k进行奇偶讨论。
假设k为奇数。红色和绿色的数量为一奇一偶:2 * (c(k, 1) + c(k, 3) + c(k, 5) +……)* c(n, k) * 2^(n - k)   (当中要乘以2,是由于能够分别选择红、绿色为奇数)
假设k为偶数,红色和绿色的数量所有为奇数:(c(k, 1) + c(k,
3) + c(k, 5) +……)* c(n, k) * 2^(n - k) (这里不须要乘以2)
而 c(k,
1) + c(k, 3) + c(k, 5) +…… = 2^(k - 1)
所以,最后的表达式为:
4^n - 2^n*c(n, 1) - 2^(n - 1)*c(n, 2) - 2^n*c(n, 3) - 2^(n-1)*c(n, 4)-…… = 4^n - 2^n*2^(n-1) - 2^(n-1)*(2^(n-1)-1) = 4^(n-1) + 2^(n-1)

代码:
/*
ID: wuqi9395@126.com
PROG:
LANG: C++
*/
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<fstream>
#include<cstring>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#define INF (1<<30)
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))
#define For(i, n) for (int i = 0; i < n; i++)
typedef long long ll;
using namespace std;
const int mod = 10007;
int multi_pow(int a, int k, int mod) {
int ans = 1;
while(k) {
if (k & 1) ans = (ans * a) % mod;
k >>= 1;
a = (a * a) % mod;
}
return ans;
}
int main () {
int t, n;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
int ans = multi_pow(2, n - 1, mod);
ans = (ans * ans) % mod + ans;
printf("%d\n", ans % mod);
}
return 0;
}

[POJ 3734] Blocks (矩阵高速幂、组合数学)的更多相关文章

  1. POJ 3734 Blocks 矩阵递推

    POJ3734 比较简单的递推题目,只需要记录当前两种颜色均为偶数, 只有一种颜色为偶数 两种颜色都为奇数 三个数量即可,递推方程相信大家可以导出. 最后来个快速幂加速即可. #include< ...

  2. poj 2778 AC自己主动机 + 矩阵高速幂

    // poj 2778 AC自己主动机 + 矩阵高速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自 ...

  3. poj 3233(矩阵高速幂)

    题目链接:http://poj.org/problem?id=3233. 题意:给出一个公式求这个式子模m的解: 分析:本题就是给的矩阵,所以非常显然是矩阵高速幂,但有一点.本题k的值非常大.所以要用 ...

  4. [POJ 3150] Cellular Automaton (矩阵高速幂 + 矩阵乘法优化)

    Cellular Automaton Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 3048   Accepted: 12 ...

  5. POJ 3613 Cow Relays (floyd + 矩阵高速幂)

    题目大意: 求刚好经过K条路的最短路 我们知道假设一个矩阵A[i][j] 表示表示 i-j 是否可达 那么 A*A=B  B[i][j]  就表示   i-j 刚好走过两条路的方法数 那么同理 我们把 ...

  6. POJ 3070 Fibonacci(矩阵高速功率)

    职务地址:POJ 3070 用这个题学会了用矩阵高速幂来高速求斐波那契数. 依据上个公式可知,第1行第2列和第2行第1列的数都是第n个斐波那契数.所以构造矩阵.求高速幂就可以. 代码例如以下: #in ...

  7. UVA 11551 - Experienced Endeavour(矩阵高速幂)

    UVA 11551 - Experienced Endeavour 题目链接 题意:给定一列数,每一个数相应一个变换.变换为原先数列一些位置相加起来的和,问r次变换后的序列是多少 思路:矩阵高速幂,要 ...

  8. UVA10518 - How Many Calls?(矩阵高速幂)

    UVA10518 - How Many Calls?(矩阵高速幂) 题目链接 题目大意:给你fibonacci数列怎么求的.然后问你求f(n) = f(n - 1) + f(n - 2)须要多少次调用 ...

  9. HDU2842-Chinese Rings(递推+矩阵高速幂)

    pid=2842">题目链接 题意:求出最少步骤解出九连环. 取出第k个的条件是,k-2个已被取出,k-1个仍在支架上. 思路:想必九连环都玩过吧,事实上最少步骤就是从最后一个环開始. ...

随机推荐

  1. Window vagrant 安装部署【转】

    回想以前,想要安装个虚拟机是多么的麻烦.先要费尽心机找到想要的操作系统镜像文件,然后安装虚拟化软件,按照其提供的GUI界面操作一步步创建,整个过程费时费力.但是,自从使用了Vagrant以后,咱腰不酸 ...

  2. 湖南省第六届大学生程序设计大赛原题 F Biggest Number (UVA1182)

    Biggest Number http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30851#problem/F 解题思路:DFS(检索)+BF ...

  3. ListVeiw新增记录及 滚动条移动到指定位置

    C# 自带的ListView控件的滚动条移动到指定位置. lvwList为ListView控件 lvwList.EnsureVisible(lvwList.Items.Count - 1); 新增记录 ...

  4. ASP.NET批量下载服务器端指定目录文件

    //遍历服务器指定文件夹下的所有文件 string path = "uploads/Image/"; string serverPath = Server.MapPath(path ...

  5. performSelector的方法

    在此我对performSelector系列方法进行了总结 1. - (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSe ...

  6. web开发常用样式

    1.div保持底部浮动(不受滚动条影响) position:fixed;_position:absolute;bottom:0px;_bottom:0px;_margin-top:expression ...

  7. 基于nginx的HLS简单服务器搭建

    一,首先搭建nginx服务器: 1.1,选定源码目录 选定目录 /usr/local/HLS cd /usr/local/HLS 1.2,安装PCRE库 cd /usr/local/HLS 到www. ...

  8. 有关SetTimer函数的用法

    1 )用WM_TIMER来设置定时器 先请看SetTimer这个API函数的原型 UINT_PTR SetTimer( HWND hWnd, // 窗口句柄 UINT_PTR nIDEvent, // ...

  9. 多线程中遇到ASSERT(pMap->LookupPermanent(hWndOrig) == NULL);怎么解决

    XP下用VC开发的程序,在一个主线程调用3   个线程,线程之间要共享数据,结果总出现wincore.cpp   line   980   ASSERT(pMap-> LookupPermane ...

  10. Gruntjs构工具学习视频

    在这里推荐一个Gruntjs的学习视频,非常不错! http://www.imooc.com/learn/30