PTA—L2-020-功夫传人
直达题目点我!
直接切入主题
思路
- 设定一个数组a,用于存储对应下标 i这个人 是第几代传人(a[i]表示),然后后面计算这个人的功力就是 pow(1-0.01×r , a[i])×z 咯
- 然后就是如何存这个a数组。很简单,存这个数组之前我们是知道它的师傅编号(假设K)的,所以弟子就是第a[k]+1代咯
- 但是这样有一个问题,就是如果师傅是第几代传人还没说怎么办?这样我们就需要一个book数组用于标记我们是否知道这个人是第几代0->不知道 1->知道,知道的,就跳入上面的编号2,不知道的,我们就用一个二维数组d来存这个人的信息(包括不知其底细的弟子与他的师傅),不知底细就是说不知道他是第几代咯
- 然后对于得道者,当然特别关照咯,用b数组存得道者的编号,c数组存这个得道者对应的功力级数(相对于他师傅而言的,比如师傅是第四代,那么得道者的功力就是 pow(1-0.01×r,4)×c[i]×z )
- 最后别忘了我们还有一部分人没有处理呢,也就是那些之前不知道师傅底细的人,我们直接遍历d数组,然后将不知道自己底细的人进行处理就好啦,很简单,就是他的师傅代数+1咯(当所有输入结束时,他师傅的底细肯定清楚了)
- 最后遍历b和c数组,将得道者功力求和输出就好啦,这里要注意得道者功力的范围最大是10^10,所以需要用double来存这个sum值咯
AC代码
#include <stdio.h>
#include <math.h>
int main()
{
int n,i,j;
double z,r;
scanf("%d %lf %lf",&n,&z,&r);
int a[n] = {0},b[n],c[n],top1 = 0; //a代表第i个人是第几代传人
for(i=1;i<n-1;i++) // 1~n-1 至少是第一代传人
a[i] = 1;
int book[n]={0}; //用于标记是否已知此弟子的师傅
int d[n][2],top2 = 0; //标记未知师傅等级的人 0:自己编号 1:师傅编号
book[0] = 1;
for(i=0;i<n;i++)
{
int m;
scanf("%d",&m);
for(j=0;j<m;j++)
{
int x;
scanf("%d",&x);
if(book[i] == 1)
{
a[x] = a[i]+1;
book[x] = 1;
}
else
{
d[top2][0] = x;
d[top2][1] = i;
top2++;
}
}
if(m == 0)
{
int lev;
scanf("%d",&lev);
b[top1] = i; //表示i这个师傅的弟子是个得道者
c[top1] = lev; //此弟子的倍增数
top1++;
}
}
for(i=0;i<top2;i++)
{
int x = d[i][0]; //弟子
int y = d[i][1]; //师傅
a[x] = a[y]+1;
}
double sum = 0;
for(i=0;i<top1;i++)
{
int sf = b[i]; //得道者的师傅
double k = pow(1.0-0.01*r,a[sf])*z*c[i]; //功力
sum += k;
}
printf("%ld",long(sum));
return 0;
}
注明一下,虽然是C的语法,但是目前有些C的编译器不支持定义数组时它的个数不能是变量,所以PTA用C提交会报错QAQ,还是得用C++的编译器提交QAQ。