洛谷刷题日记.5

53 阅读2分钟

P1464 Function

题目描述

对于一个递归函数 w(a,b,c)w(a,b,c)

  • 如果 a0a \le 0b0b \le 0c0c \le 0 就返回值 11
  • 如果 a>20a>20b>20b>20c>20c>20 就返回 w(20,20,20)w(20,20,20)
  • 如果 a<ba<b 并且 b<cb<c 就返回 w(a,b,c1)+w(a,b1,c1)w(a,b1,c)w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c)
  • 其它的情况就返回 w(a1,b,c)+w(a1,b1,c)+w(a1,b,c1)w(a1,b1,c1)w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)

这是个简单的递归函数,但实现起来可能会有些问题。当 a,b,ca,b,c 均为 1515 时,调用的次数将非常的多。你要想个办法才行。

注意:例如 w(30,1,0)w(30,-1,0) 又满足条件 11 又满足条件 22,请按照最上面的条件来算,答案为 11

输入格式

会有若干行。

并以 1,1,1-1,-1,-1 结束。

输出格式

输出若干行,每一行格式:

w(a, b, c) = ans

注意空格。

输入输出样例 #1

输入 #1

1 1 1
2 2 2
-1 -1 -1

输出 #1

w(1, 1, 1) = 2
w(2, 2, 2) = 4

说明/提示

数据规模与约定

保证输入的数在 [9223372036854775808,9223372036854775807][-9223372036854775808,9223372036854775807] 之间,并且是整数。

保证不包括 1,1,1-1, -1, -1 的输入行数 TT 满足 1T1051 \leq T \leq 10 ^ 5

题目已经告诉我们是个递归函数了 且已经给出我们递推式是怎么样的 所以难度下降了很多 一开始我还以为要去用a, b,c的关系去推递推式 看了答案才发现自己想错了 然后问题其实在于有些组合的数如果用递推的话 会导致递推的太多内存爆了 所以我们可以把在我们要的组合下的数给算出来然后直接去相加就好了 这样我们就不会调用很多个函数了就不会爆内存 以下就是代码

int temp[21][21][21];//超出了20的数直接变20所以我们设到20就好 0不要是为了好对应
int w(int a,int b,int c){
if(a<=0||b<=0||c<=0){return 1;}
else if(a>20||b>20||c>20){return w(20,20,20);}
else if(temp[a][b][c]!=-1){reutrn temp[a][b][c];}
else if(a<b&&b<c){return w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);}
else {return w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b-1,c)-w(a-1,b-1,c-1);}
}//构造一个递推函数 同时进行数据的储存 注意要按照他题目说的顺序来排 要把temp的检查放在后面 防止越界

int main(){
for(int i=1;i<=20;i++){
 for(int u=1;u<=20;u++){
 for(int o=1;o<=20;o++){
  temp[i][u][o]=-1;//把记录数据的数组进行初始化 后面才能检查是不是记录过了
  }
 }
}
int a,b,c;
while(1){
scanf("%d %d %d",&a,&b,&c);
if(a==1&&b==1&&c==1){break;}//读到-1,-1,-1时就退出整个循环
printf("w(%d,%d,%d)=%d",a,b,c,w(a,b,c));
printf("\n");//我们每次读到一个数我们就去输出 
}
return 0;
}