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. Grizzly开发Echoserver实战

    Grizzly开发Echoserver实战 作者:chszs,转载需注明. 博客主页:http://blog.csdn.net/chszs 用Java编写可伸缩的server应用是有难度的.用Java ...

  2. maven 打包源文件

    1.The source plugin can be used to create a jar file of the project sources from the command line or ...

  3. [CSAPP笔记][第十章 系统级I/O]

    第十章 系统级I/O 输入/输出(I/O) : 是指主存和外部设备(如磁盘,终端,网络)之间拷贝数据过程. 高级别I/O函数 scanf和printf <<和>> 使用系统级I ...

  4. 代码,显示IPhone剩余磁盘空间

    #include <sys/mount.h> //这段代码示范怎么取得 iPhone 的剩余磁盘空间,还有全部磁盘空间 long long freeSpace() { struct sta ...

  5. CodeManage 源代码管理器v2.0发布

    下载地址 欢迎大家提出宝贵的意见和bug

  6. 解决Android AVD启动报错问题

    好不容易从ADT Bundle转为Android Studio的开发环境,一路荆棘,现在又遇到了模拟器的问题,本来直接用真机调试程序会更快些,但是为了模拟多种系统不得不开启AVD. 废话不说,问题和解 ...

  7. C语言结构体的字节对齐

    Test Code: #include <iostream> #include <cstring> using namespace std; struct A{ int a; ...

  8. “Win”组合键

    Windows组合键功能: 单独按下显示或隐藏 [开始] 功能表. +Break 显示 [系统内容] 对话方块. +D 显示桌面. +M 最小化所有的视窗. +Shift+M 还原最小化的视窗. +E ...

  9. 使用json常用到的包有以下六个

    使用json常用到的包有以下六个 1. commons-logging-1.0.4.jar 2. commons-lang-2.3.jar 3. commons-collections-3.2.jar ...

  10. ecshop中404错误页面设置

    在ecshop系统当中,比如你随意将商品详细页面的地址中的ID修改为一个不存在的商品ID,ecshop会自动跳转到首页.ecshop在这方面做得非常的差,甚至导致了很多的站不被搜索引擎收录.最模板提供 ...