第一次写博客,引发我写博客的动机就是,我发现我实在是太蠢了,昨天下午一道5分钟可以敲完的题目,我硬生生敲了四个多小时,编程真的是一个很奇妙的事情我只能说。。
下面我主要来分享一下我的脑残行为。
首先给出题目:
Description
人称AC之神的QIGe最近一直忙着培养NOI高手,为了鼓励NOI高手, QiGe做了若干雨花石项链,作为对表现优秀的选手的奖励.他会挑选一个雨花石作为这串项链的开始,然后一个接一个连起来,现在他有三种颜色的雨花石,红(Red)、绿(Green)、蓝(Blue),做项链的时候他要求每相邻的2个雨花石不能相同的颜色,尽管最后一步把首尾连接起来的工作QiGe不需要去做,但也必须保证首尾2个雨花石它们是不同颜色。你知道QiGe有多少种串项链的方法吗?
Input
输入数据包含多个测试实例,每个测试实例占一行,由一个整数N组成,(0<n<=50)。
Output
对于每个测试实例,请输出全部的满足要求的排法,每个实例的输出占一行。
Sample Input
1
2
Sample Output
3
6
这道题目的难点其实就是在算法思路这一块,也就是需要找到其中的规律,说句实话,如果没有经常接触这类题目,新手一接触确实会一头雾水,就比如我一开始接触这道题目,真的非常自闭,感觉自己水平还有很大很大的提升空间。
我这篇文章不会重点讲算法,因为算法只要给出了,自己再想想就非常简单。
算法:
设n个石头围成项链种类为a[n],根据题目要求一开始就定义int a[50],然后根据规律可以得出a[n]=a[n-1]+a[n-2]*2(这里不懂的话可以看下这位兄弟的博客,https://blog.csdn.net/zstuyyyyccccbbbb/article/details/103840127)
然后是不是就很简单了?对,没错,我也是这么觉得的,但是我犯了一个致命的错误,希望后来人不要和我一样,浪费了四个小时!
下面是我花了四个小时写的非常麻烦的代码。
为什么说麻烦?因为本来这个问题可以用整型加个for循环一下子就解决了,但是这里面有个小bug,就是从第32个开始,整数就会很大很大,导致超过整型的范围,但幼小天真的我仅仅只能找到long这个类型,结果还是太小,最后我竟然愚蠢的放弃了这条最简单的道路,走向了荆棘丛生的杂草堆,能让我专门写一篇文章来骂我自己的愚蠢😀。
我的愚蠢想法就是既然整型存储不了的话,那么就用字符型存储呗,于是我踏上了这条不归路,这个过程可以说是相当曲折,我没有时间在这里一一阐述,就给出相应的代码和注释,如果有看的下去的兄弟应该能发现我的愚蠢。。
愚蠢代码
#include <stdio.h>
#include<string.h>
int main()
{
char a[50][100]={"3","6","6"};
int i;
for(i=3;i<50;i++) /*生成前五十个结果*/
{
cal_char(a,a[i-1],a[i-2],i);
}
int n;
while(scanf("%d",&n)!=EOF)
{
printf("%s\n",a[n-1]);
}
}
void cal_char(char a[][100],char b[],char c[],int i) /*这里有个小细节,就是第一个变量不能写成a[][],要不然用字符串函数赋值的时候会出问题*/
{
char d[100],o[100]; /*d用来当作赋值的中介,o是c的复制品*/
strcpy(o,c); /*之所以要有复制品,是因为之后要让b,c俩个数组长度对齐,不足的地方补0,为了不影响最后的输出,因此不能直接改变c的值*/
int len_b=strlen(b),len_o=strlen(o); /*确定俩个数组长度*/
while(strlen(b)!=len_o) /*让俩个长度对齐*/
{
int j;
for(j=len_o;j>=1;j--)
{
o[j]=o[j-1];
}
o[0]='0';
len_o++;
}
o[len_o]='\0';
int j=len_b-1,forward=0; /*用j指向b和c的最后一个字符,forward是进位*/
d[len_b+1]='\0'; /*初始化间接数组*/
for(j;j>=0;j--) /*这个计算的过程很简单,大家应该随便看看就会了*/
{
int x;
x=b[j]-'1'+1+(o[j]-'1'+1)*2+forward;
forward=0;
if(x>=10)
{
forward=x/10;
x=x%10;
}
char y=x+'0';
d[j+1]=y; /*这里面d的第一位要留出来,因为之后有可能要加上1*/
}
if(forward==1) /*要加1的情况*/
{
d[0]='1';
strcpy(a[i],d);
}
else /*不要加1的情况,此时把j整体向前移动一位*/
{
int j;
for(j=0;d[j]!='\0';j++)
{
d[j]=d[j+1];
}
strcpy(a[i],d);
}
}
是不是很麻烦?对,没错,麻烦的不行。。
之后我才从一位兄弟那边得知,一开始的时候若是我改成long long型,就能容得下这么大的数了,也不用向我这样花里胡哨搞半天。
我。。。。。。。。。。。
下面给出代码。
正常代码
#include <stdio.h>
#include<string.h>
int main()
{
long long a[50];
a[0]=3;
a[1]=6;
a[2]=6;
int i;
for(i=3;i<50;i++)
{
a[i]=a[i-1]+a[i-2]*2;
}
int n;
while(scanf("%d",&n)!=EOF)
{
printf("%lld\n",a[n-1]);
}
}
是不是感觉很简单?
写到这里我真的感觉我蠢得不行!真的是任重道远啊。真的还有很多不足,昨天经历了一个晚上的自闭,今天还是得爬进来补作业,尽管生活很难,但还得坚持,我不知道这样有没有意义,我只是不想体验放弃的感觉。。。
首先声明,我写博客很大程度是为了记录和分享我的编程之路,如果后来人是在百度上面搜到我的文章,动机不是为了知识本身,而是为了应付题目的话,我话摆在这里,借鉴可以,但是一定要转化成自己的知识,不要只抄,然后没弄懂,那还不如直接花钱请人帮你做了,我一直秉持的原则就是,你真不想干某件事,而这件事又在你看来是没有意义的话,倒还不如用钱解决,说白了就是用钱买时间,没有必要在一些对你没有意义的地方花过多时间,倒还不如用这么点时间去做一些更有意义的事情。
如果觉得有帮助,可以关注一下我的公众号,我的公众号主要是将这些文章进行美化加工,以更加精美的方式展现出来,同时记录我大学四年的生活,谢谢你们!