多米诺骨牌(domino)
(domino.c/cpp)
问题描述
小牛牛对多米诺骨牌有很大兴趣,然而她的骨牌比较特别,只有黑色和白色的两种。她觉得如果存在连续三个骨牌是同一种颜色,那么这个骨牌排列便是不美观的。现在她有n个骨牌要来排列,她想知道不美观的排列的个数。由于数字较大,数学不好的她不会统计,所以请你来帮忙。希望你帮她求出不美观的排列的个数。
输入数据
只有一个正整数,即要排列的骨牌个数。
输出数据
一个数,即不美观的排列个数。
样例输入
4
样例输出
6
样例解释
有四种不美观的排列。
黑黑黑黑,白白白白,黑黑黑白,白白白黑,黑白白白,白黑黑黑
数据范围
20%的数据,n<=60;
50%的数据,n<=6000;
100%的数据,n<=10000。
时间限制: 1 sec
空间限制: 256 MB
思路:首先先计算美观的排列个数,推导可知美观的排列个数T(n)=T(n-1)+T(n-2),且T(1)=2;T(2)=4;最后用总的排列次数2^n-T(n)就是不美观的排列次数,难点是大数的加减,需要用到高精度加减法。
#include<iostream>
#include<stdio.h>
using namespace std;
const int length = 100000000;
const int L2 = 380;
void HighPreAdd(int add1[], int add2[] ,int add3[])//高精度加法
{
int j = 0, c = 0;//c进位标志
while (add2[j] != -1 || (c == 1))//若最高8位为-1且无进位,则退出循环
{
int m;
if (add2[j] == -1)
{
add3[j] = c;
c = 0;
}
else if (add1[j] == -1)
{
add3[j] = add2[j] + c;
c = 0;
}
else
{
m = add1[j] + add2[j] + c;
if (m >= length)
{
c = 1;
m -= length;
add3[j] = m;
}
else
{
add3[j] = m;
c = 0;
}
}
j++;
}
}
void HighPreSub(int sub1[], int sub2[])//高精度减法
{
int j = 0;
while (sub1[j]!=-1)//循环到被减数的最高位+1时退出
{
sub2[j] = sub2[j]-sub1[j];
j++;
}
for (int n = 0;n < j;n++)
{
if (sub2[n] < 0)
{
sub2[n + 1]--;
sub2[n] += length;
}
}
}
int main()
{
int num,t,count=0, *p;
int *Add1=new int[L2];//2个操作数;
int *Add2=new int[L2];
int *TN = new int[L2];//TN为美观的数量,total一开始为总的排列次数,后为完美排列的次数。
int *total = new int[L2];
for (int i = 0;i < L2;i++)
{
Add1[i] = -1;
Add2[i] = -1;
TN[i] = -1;
total[i] = -1;
}
Add1[0] = 2;
Add2[0] = 4;
cin >> num;
for (int i = 3;i <= num;i++)
{
HighPreAdd(Add1, Add2,TN);
if (i != num )
{
p = Add1;//元素互换
Add1 = Add2;
Add2 = TN;
TN = p;
}
}
for (int i = 0;i < L2;i++)
{
Add1[i] = -1;
Add2[i] = -1;
}
Add1[0] = 2;
Add2[0] = 2;
for (int i = 1;i < num;i++)//表示2^n
{
HighPreAdd(Add1, Add2, total);
if (i != num - 1)
{
p = Add1;
Add1 = total;
Add2 = total;
total = p;
}
}
HighPreSub(TN, total);//高精度减法
while (total[count] != -1)//定位total最高8位的下标
count++;
count--;
t = count;
while ((count + 1) != 0)
{
if (t != count)
printf("%08d", total[count]);
else
printf("%d", total[count]);
count--;
}
return 0;
}