http://poj.org/problem?id=2033
这是一道DP的题,但是DP我还不会,所以被我当做找规律做了。
本来找规律以为是斐波那契数, 但后来发现其中有存在中断的情况。然后我把中断的情况分段,每段套用斐波那契数然后相乘,然后样例轻松地过了。提交后wa了。然后认为这种方法行不通,放弃了乘法的想法。然后遇到中断点时,后面一段继承上一段的值,转而用斐波那契数的初始化定义,后面一项等于前两项的和,样例也轻松过了,然后又是wa。思索了好半天才发现,样例给的数虽然有连续两数不能构成小于26的情况,但是样例没有给出出入存在0的情况,比如说是122089这组数,其中0只能和前面的2构成20。于是,改了一下flag数组,把0的情况加进去后修改了一下初始化,才a了。
初始化的时候注意前两项的特殊情况。
后来看了一下discuss发现我之前的一种分段相乘的想法也是可行的,wa是因为没有考虑0的情况。
我的代码:
#include<stdio.h>
#include<string.h>
long long a[500010];
long long flag[500010];
long long ans[500010];
int main()
{
long long i, sum, num, len;
char str[500010];
while(scanf("%s", str) && strcmp(str, "0")!=0)
{
sum=0;
len=strlen(str);
flag[0]=0;
for(i=1; i<len; i++)
{
if(flag[i-1]==2)
flag[i]=0;
else if((str[i]-'0')==0)
{ flag[i]=2; flag[i-1]=0; }
else
{
num=(str[i]-'0')+(str[i-1]-'0')*10;
if(num<=26 && num>=1)
flag[i]=1;
else flag[i]=0;
}
}
ans[0]=1;
sum=1;
for(i=1; i<len; i++)
{
if(flag[i]==2)
{
if(i==1) { ans[i]=1; ans[i-1]=0; }
else
ans[i]=ans[i-2];
}
else if(flag[i]==1)
{
if(ans[i-1]==1 && i==1) ans[i]=2;
else ans[i]=ans[i-1]+ans[i-2];
}
else
{
ans[i] =ans[i-1];
}
sum = ans[i];
}
printf("%I64d\n", sum);
}
return 0;
}