/*有排成一行的n个方格,用红粉绿三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两个也不同色,求全部的满足要求的涂法*/
我总结了三个公式
第一种:①假设n个方格的涂法为f(n)则 f(n)=f(n-1)+2*f(n-2)
第二种:②f(n)=(3*2^n-1)-f(n-1)
第三种:③ n为偶数时 f(n)=2+2^n n为奇数时f(n)=2^n-2
①假设n个方格的涂法为f(n)则 f(n)=f(n-1)+2*f(n-2)
怎么来的呢 我解释一下
假设有n(n>=3)个格子,这n个格子有f(n)种方法,而这f(n)种方法是在且首尾两个不同的前提下得到的 如果没有这个前提 方法会更多 当我加上第n+1个格子的时候 这时候对于第n个格子就没有上面的条件限制了 所以f(n+1)是要分情况讨论的
1 如果第n个格子与第一个不同 也就是说第n+1个格子只有一种选择 那么这种情况就和 f(n)是一样的 即 此类情况下的方法数量上=f(n)
2 如果第n个格子与第1个格子颜色相同 那么 也就是说第n-1个格子与第1个格子是不相同的 不先考虑第n+1个格子
先考虑 第n个格子与第1个格子颜色相同的情况有多少 显然这种情况有f(n-1)种 即 这种情况可以看作按照题目要求得到f(n-1)后直接在第n个格子上涂上了与第一个相同的颜色
而 因为第n个与第一个的颜色相同 导致了第n+1个格子有2种颜色的选择,即此类情况有 2*f(n-1)种
综上 f(n+1)=f(n)+2f(n-1)
# include <stdio.h>
# define N 51
int main(){
__int64 arr[N]={0,3,6,6,0},num,i;
for(i=4;i<N;i++)
arr[i]=arr[i-1]+2*arr[i-2];
while(scanf("%d",&num))
printf("%I64d\n",arr[num]);
return 0;
}
②对于n个格子 先不考虑第n个与第一个相同的情况
那么 一旦第一个格子三种颜色选择一个确定了 剩下的n-1个格子中 每一个有两种选择 有3*2^n-1
此时再考虑第n个格子与第一个格子相同的情况 这种情况可以看作按照题目要求得到f(n-1)后直接在第n个格子上涂上了与第一个相同的颜色 有f(n-1)中
公式 : f(n)=(3*2^n-1)-f(n-1) 当然用这种方式编程确实亦可以
③这个题目是可以推出公式的 用等比数列的和可以得到下面的公式
n为偶数时 f(n)=2+2^n
n为奇数时f(n)=2^n-2
具体推理:
如果N很大时 就可以借助这个公式进行推理
下面的代码可以求出1---20000之间的任何一个 半秒内出结果 可以改改参数 求更高的数
2^N次幂的最低位一定是 2 4 6 8 而且不会出现 9998这种情况
# include <stdio.h>
# define N 780
# define MAX 20000 //第2的20000次方大约需要753个int的空间 每个int存8位
# define WEI 100000000//每8位存一段
int gainint(int *p,int a,int b);//如果是奇数返回1 偶数返回0
int chengfang(int m,int data[]);//计算2的m次幂返回位数
void main(){
int data[N]={0},n,index,Flag;
printf("请输入n:(1--%d):",MAX);
Flag=gainint(&n,1,MAX);
index = chengfang(n,data);
data[1]+=2*(Flag?-1:1);
if (index) /* 检验数组是否溢出,若未溢出,则打印阶乘值 */
printf("%d",data[index--]);
while(index>0)
printf("%08d",data[index--]);
while(getchar()!='\n');
}
int gainint(int *p,int a,int b)
{
int c[2]={0,1};
do{
scanf("%d",p);
while(getchar()!='\n');
if(*p>b||*p<a)
printf("输入有误,请重新输入(%d--%d):",a,b);
}while(*p>b||*p<a);
return *p%2; //如果是奇数返回1 偶数返回0
}
int chengfang(int m,int data[])
{
int i, j, k;
int index = 1; //位数暂定为1
data[1]=1; /* 初始化,令2^0=1 */
for (i=1; i<=m; i++) /* 计算2的m次幂*/
{
for (j=1; j<=index; j++)
data[j]=data[j] * 2;/*每一位数字都乘以2,模仿乘法计算*/
for (k=1;k<index; k++)
if (data[k]>=WEI)
{
data[k+1]+=data[k]/WEI; /* 当前位向前进位 */
data[k]%=WEI; /*当前位进位之后的值 */
}
/* 单独处理最高位,若计算之后的最高位>=WEI,则位数index加1 */
while (data[index] >=WEI && index <= N-1)
{
data[index+1] = data[index]/WEI; /* 向最高位进位 */
data[index++]%=WEI; /* 进位之后的值 位数index加1 */
}
}
return index <= N-1?index:0;/* 检验数组是否溢出,若未溢出,则返回位数 */
}