题目描述
您将一个长度为 nn 的数组 aa 和一个整数 xx 给了机器人。机器人的操作将会遵循以下原则:对于数组的元素进行迭代,当前的元素为 qq。如果 qq 被 xx 整除,那么机器人会将 xx 个整数 \frac{q}{x}x**q 添加到数组的末尾,然后移到下一个元素。否则,机器人停止工作。
请在机器人停止工作时确定数组所有值的总和。
输入格式
第一行包含一个整数 t(1\le t\le100)t(1≤t≤100) 输入数据的组数。
接下来对于每组数据包含一个整数 n,x(1\le n\le 100000,1\le x\le 10^9)n,x(1≤n≤100000,1≤x≤109)数组的长度和机器人的工作值。
接下来的一行包含 nn 个整数, a_1,a_2,\cdots ,a_na1,a2,⋯,a**n 表示 aa 数组。
确保所有测试用例的值 nn 的总和不超过 10 ^ 5105。
转载至繁凡大佬:https://fanfansann.blog.luogu.org/solution-cf1471b
首先第一步还是分析性质。
我们发现 q 能被 x 整除,那么在数列的末尾加上 x 份
q
x
\cfrac{q}{x}
xq,对答案的贡献实际上就是
x
×
q
x
=
q
x\times \cfrac{q}{x}=q
x×xq=q。这是解题的关键。我们发现不论是第一次还是第 n 次,对答案的贡献都是 q,这样我们就不用暴力地按照题意模拟求总价值,而是直接加上 q 即可。我们发现任何一个数,哪怕本来能被 x 整除,但是把除数放到最后末尾,指针指向的时候,总有一次,会被除尽,也就是指针暂停,末尾不会再增加数字,可以开始计算最终的答案了。也就是一旦除出来的数不能被 x 整除了,就 break
退出了。因为我们要每次加上 q ,所以我们不能改变原数组,而我们需要一直除,来判断是否能继续被 x 整除,所以我们可以把数组 a copy
到数组 b。
个人补充:
为什么除过x之后重新判断新添加的数能不能被再次添加,即能被再次整除后对答案的贡献还是q。是因为,我们上一次得到的新的元素一共是x个,每一个是 q x \cfrac{q}{x} xq, q x \cfrac{q}{x} xq还能被x整除,那么得到的就是 q x ∗ x \cfrac{q}{x *x} x∗xq,一共有x个 q x \cfrac{q}{x} xq能被整除添加,对答案的贡献就是 q x ∗ x ∗ x ∗ x = q \cfrac{q}{x*x}*x*x=q x∗xq∗x∗x=q
// Problem: B. Strange List
// Contest: Codeforces - Codeforces Round #694 (Div. 2)
// URL: https://codeforces.com/contest/1471/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// Code by: ING__
//
// Powered by CP Editor (https://cpeditor.org)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define ll long long
#define re return
#define Endl "\n"
#define endl "\n"
using namespace std;
typedef pair<int, int> PII;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
int T;
int n, x;
int a[100000 + 10];
int b[100000 + 10];
int main(){
cin >> T;
while(T--){
cin >> n >> x;
ll summ = 0;
for(int i = 1; i <= n; i++){
scanf("%d", a + i);
b[i] = a[i];
summ += a[i];
}
int f = 1;
while(1){
for(int i = 1; i <= n; i++){
if(a[i] % x == 0){
summ += b[i];
a[i] /= x;
}
else{
f = 0;
break;
}
}
if(!f){
break;
}
}
cout << summ << endl;
}
return 0;
}