题目描述:
DreamGrid has n n n integers a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,…,an. DreamGrid also has m m m queries, and each time he would like to know the value of ∑ 1 ≤ i ≤ n ⌊ a i ⌈ log p a i ⌉ ⌋ \sum\limits_{1 \le i \le n}\Bigl\lfloor \frac{a_i}{\lceil\log_{p}a_i\rceil}\Bigr\rfloor 1≤i≤n∑⌊⌈logpai⌉ai⌋ for a given number p p p, where ⌊ x ⌋ = max { y ∈ Z ∣ y ≤ x } \lfloor x \rfloor = \max\{y \in \mathbb{Z} \mid y \le x\} ⌊x⌋=max{y∈Z∣y≤x}, ⌈ x ⌉ = min { y ∈ Z ∣ y ≥ x } \lceil x \rceil = \min\{y \in \mathbb{Z} \mid y \ge x\} ⌈x⌉=min{y∈Z∣y≥x}.
Input
There are multiple test cases. The first line of input is an integer T T T indicating the number of test cases. For each test case:
The first line contains two integers n n n and m m m ( 1 ≤ n , m ≤ 5 × 1 0 5 1 \le n, m \le 5 \times 10^5 1≤n,m≤5×105) – the number of integers and the number of queries.
The second line contains n n n integers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an ( 2 ≤ a i ≤ 1 0 9 2 \le a_i \le 10^{9} 2≤ai≤109).
The third line contains m m m integers p 1 , p 2 , … , p m p_1, p_2, \dots, p_m p1,p2,…,pm ( 2 ≤ p i ≤ 1 0 9 2 \le p_i \le 10^{9} 2≤pi≤109).
It is guaranteed that neither the sum of all n n n nor the sum of all m m m exceeds 2 × 1 0 6 2 \times 10^6 2×106.
Output
For each test case, output an integer ( ∑ i = 1 m i ⋅ z i ) m o d 1 0 9 (\sum\limits_{i=1}^{m} i \cdot z_i) \bmod 10^9 (i=1∑mi⋅zi)mod109, where z i z_i zi is the answer for the i i i-th query.
Sample Input
2
3 2
100 1000 10000
100 10
4 5
2323 223 12312 3
1232 324 2 3 5
Sample Output
11366
45619
翻译:
输入n和m,数组的长度为n,第二行的n个数表示a数组,接下来输入m个p,
对于每一个p,遍历a数组,求得
Z
i
Z_i
Zi
∑
1
≤
i
≤
n
⌊
a
i
⌈
log
p
a
i
⌉
⌋
\sum\limits_{1 \le i \le n}\Bigl\lfloor \frac{a_i}{\lceil\log_{p}a_i\rceil}\Bigr\rfloor
1≤i≤n∑⌊⌈logpai⌉ai⌋
可以得到m个这样的数
Z
i
Z_i
Zi
输出的结果: ( ∑ i = 1 m i ⋅ z i ) m o d 1 0 9 (\sum\limits_{i=1}^{m} i \cdot z_i) \bmod 10^9 (i=1∑mi⋅zi)mod109
分析:
分母的取值范围:
每一个
a
i
a_i
ai的范围为
[
2
,
1
0
9
]
[2,10^9]
[2,109],每一个p的范围为
[
2
,
1
0
9
]
[2,10^9]
[2,109],
对于分母:
⌈
log
p
a
i
⌉
{\lceil\log_{p}a_i\rceil}
⌈logpai⌉
int的范围为231-1(即2147483647)
分母的范围可以最小为1,31可以为上限
枚举每一个分母的值,对:
a
i
⌈
log
p
a
i
⌉
\frac{a_i}{\lceil\log_{p}a_i\rceil}
⌈logpai⌉ai 进行前缀和
for(int k=1; k<=30; k++)///枚举分母
for(int i=1; i<=n; i++)
sum[i][k]=sum[i-1][k]+a[i]/k;
输入每一个p,求的一个 Z i Z_i Zi:
p和每一个 a i a_i ai的大小密不可分,并且有向上取整,对a数组从小到大排序,可以用二分解决
初始化两个值 s1=p,s2=1和index=1;
从index=1枚举分母,通过二分找到对应的区间,记录结果,更新s1和s2
for(int i=1; i<=m; i++)
{
LL ans=0,p;
cin>>p;
LL s1=p,s2=1;
int index=1;
while(true)
{
int pos1=upper_bound(a+1,a+1+n,s1)-(a+1);///upper找到第一个大于s1的下标,减去a+1,相当于又减去1,例如 2 3 4 5 upper_bound(3)返回的是位置3,但pos1=2
int pos2=upper_bound(a+1,a+1+n,s2)-(a+1);
ans+=sum[pos1][index]-sum[pos2][index];///[pos2,pos1]这个区间的分母都为index
index++;
s2=s1;
s1*=p;///分母为1找完了,再找分母为2,分母为3,,
if(pos1==n)
break;
}
res=(res+ans*i)%mod;
}
完整代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mod=1e9;
const int N=5*1e5+10;
int t,n,m;
LL a[N],sum[N][35];
int main()
{
cin>>t;
while (t--)
{
cin>>n>>m;
for (int i=1; i<=n; i++)
cin>>a[i];
sort(a+1,a+n+1);
for(int k=1; k<=30; k++)///枚举分母
for(int i=1; i<=n; i++)
sum[i][k]=sum[i-1][k]+a[i]/k;
LL res=0;
for(int i=1; i<=m; i++)
{
LL ans=0,p;
cin>>p;
LL s1=p,s2=1;
int index=1;
while(true)
{
int pos1=upper_bound(a+1,a+1+n,s1)-(a+1);
int pos2=upper_bound(a+1,a+1+n,s2)-(a+1);
ans+=sum[pos1][index]-sum[pos2][index];
index++;
s2=s1;
s1*=p;
if(pos1==n)
break;
}
res=(res+ans*i)%mod;
}
cout<<res<<endl;
}
return 0;
}