《编程思维与实践》1071.猜猜猜
题目
思路
对于首字符而言,如果后一位字符与之相同,则首位选法只有1种,不同则2种;
对于最后一位字符而言,如果前一位字符与之相同,则末位选法只有1种,不同则2种;
对于中间的字符而言,有以下几种可能:
1.中间字符与前后字符均不同且前后字符不同(abc型):则中间字符有3种选法;
2.中间字符与前后字符均不同且前后字符相同(aba型):则中间字符有2种选法;
3.中间字符与前后某一个字符相同(aac型),则中间字符有2种选法;
4.中间字符与前后两字符都相同(aaa型),则中间字符有1种选法.
以yes为例: 一共有 2 ⋅ 3 ⋅ 2 = 12 2\cdot3\cdot2=12 2⋅3⋅2=12种选法.
注意的点:
长度为1的单词只有1种选法.
代码
#include<stdio.h>
#include<string.h>
#define N 501
typedef struct{int cnt,v[N];}BIGINT;
BIGINT carry(BIGINT S,int n); //进位 n表示进制
BIGINT int2BIG(int x,int bin); //int 转换(to)成BIGINT
BIGINT mul(BIGINT S,BIGINT T); //两个大整数相乘
int main()
{
char s[1001];
scanf("%s",s);
if(strlen(s)==1)
{
printf("1");
}
else
{
BIGINT ans=int2BIG(1,10);
for(int i=0;i<strlen(s);i++)
{
if(i==0)
{
if(s[i]!=s[i+1])
{
ans=mul(ans,int2BIG(2,10));
}
}
else if(i==strlen(s)-1)
{
if(s[i]!=s[i-1])
{
ans=mul(ans,int2BIG(2,10));
}
}
else
{
if(s[i]!=s[i-1]&&s[i]!=s[i+1])
{
if(s[i-1]!=s[i+1])
{
ans=mul(ans,int2BIG(3,10));
}
else
{
ans=mul(ans,int2BIG(2,10));
}
}
else if(s[i+1]!=s[i-1])
{
ans=mul(ans,int2BIG(2,10));
}
}
}
for(int i=ans.cnt-1;i>=0;i--)
{
printf("%d",ans.v[i]);
}
}
return 0;
}
BIGINT carry(BIGINT S,int n) //进位 n表示进制
{
int flag=0;
for(int i=0;i<S.cnt;i++)
{
int temp=S.v[i]+flag;
S.v[i]=temp%n;
flag=temp/n;
}
if(flag) //为了加法进行的方便 可能多一位
{
S.v[S.cnt++]=flag;
}
return S;
}
BIGINT int2BIG(int x,int bin) //int 转换(to)成BIGINT
{
BIGINT R={0,{0}};
do
{
R.v[R.cnt++]=x%bin;
x/=bin;
}while(x>0);
return R;
}
BIGINT mul(BIGINT S,BIGINT T) //两个大整数相乘
{
BIGINT R={S.cnt+T.cnt,{0}}; //位数最多为两者相加
for(int i=0;i<T.cnt;i++)
{
for (int j=0;j<S.cnt;j++)
{
R.v[i+j]+=S.v[j]*T.v[i]; //依此进行普通乘法
}
}
R=carry(R,10);
if(R.v[S.cnt+T.cnt-1]==0)
{
R.cnt--; //最高位0不统计在一个大整数的位数中
}
return R;
}