B. Strange List(数学题)

题意:有T个测试,输入n个数组成一个数组a,再输入一个x。遍历这个数组,当遍历到的a[i],能被x整除时,就要在这个数组的末尾加上x个a[i]/x,然后移向下一个数,之后添加的数也要按照这个规律进行下去。当a数组中的后增加的数不能被x整除时,程序结束。求这个数组按照这个规律进行下去后,得到的总和。

题解:最开始肯定会想到暴力,但是暴力解决不了问题(呜呜呜)

所以,我们来找规律:(假设x=2,数组为4 2 8 6)

当4满足条件时,它得出了两个2,因为2也满足条件,所以得到了4个1。然后发现,它们得和均是4。这就是规律啦!

总结一下就是,当a[i]满足条件时,它加在数组末尾的数之和x*a[i]/x,还是等于a[i]。

找到规律后,求和的问题就解决了。还要注意求和的ans必须是long long,不然会爆数据的。另外,无论初始数据是什么样,都不会让遍历停止,影响遍历的只会是新增加的数。

ACcode:

int main()
{
int m, i, j;
int b, a[100100] = {0}, n;//初始化
cin >> m;
while (m--)
{
long long int ans=0,res=1,flag=1;//ans必须是long long ,因为a[i]可能=1e9,多几个可能就会爆long long
cin >> n >> b;
for (i = 0; i < n; i++)
cin >> a[i];
while(1)
{
for(j=0;j<n;j++)//因为初数组全部求和,所以res从1开始,如果之前已经求和,那么从res=6开始。
{
if (a[j] % res == 0)
ans += a[j];//增加的数的总和还是等于a[j],你可以试试x*a[j]/x,所以直接加a[j],能够节省求和时间,不用循环求解,会超时。
if (a[j] % res != 0)
{
flag = 0;//为了跳下一个循环
break;//题中说,如果有一个不能整除就停止。
}
}
res = res * b;//之后乘b,为了下一次循环,判断下次的数能否被整除(实际上就是用原始数据除以变化的res)
if (flag == 0)
break;//要跳出双重循环
}
cout << ans<<endl;
memset(a, 0, sizeof(a));//也可以省略,不会影响测试
}
return 0;
}

 

                  

 

posted @ 2021-01-27 13:28  Uiney  阅读(131)  评论(0编辑  收藏  举报