Now Loading!!!
Time Limit: 1 Second Memory Limit: 131072 KB
DreamGrid has n integers . DreamGrid also has n queries, and each time he would like to know the value of
Input
There are multiple test cases. The first line of input is an integer n indicating the number of test cases. For each test case: The first line contains two integers n and m (
) – the number of integers and the number of queries.
The second line contains n integers
(
).
The third line contains m integers (
).
It is guaranteed that neither the sum of all n nor the sum of all m exceeds
.
Output
For each test case, output an integer , where is the answer for the 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
大致题意:给你 和 ,然后让你求 .
显然,直接计算的复杂度是O(nm)的,对于 的数据来说显然是会TLE的。但是我们考虑到分母 的取值很少,只能是[2,30],所以可以考虑根据把分母相同的一起计算。首先,我们对 进行排序,然后对于每一个给定的 ,根据 的不同次方来统计。例如当考虑 时,我们要统计 。由于 已经排好序,所以我们可以用二分的方法确定满足条件的 的范围,然后用前缀和求得区间和。
这样对于每一个 ,分成 个部分计算,每个部分二分出 的范围再前缀和计算,总的复杂度O(m )。但是关于前缀和部分,要注意先求和再除以某个数字向下取整 与 先对每个数字向下取整再求和是不一样的。我们要的是后者,所以我们在预处理前缀和的时候,要根据分母的不同求多个前缀和,第i个前缀和存的是每个数字先除以i之后再求的前缀和。具体步骤见代码:
#include<bits/stdc++.h>
#define mod 1000000000
#define LL long long
#define N 500010
using namespace std;
int a[N],s[33][N],ans;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T; cin>>T;
while(T--)
{
ans=0;
int n,m;
cin>>n>>m;
//memset(s,0,sizeof(s));
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
for(int j=1;j<=32;j++)
for(int i=1;i<=n;i++)
s[j][i]=(a[i]/j+s[j][i-1])%mod;
for(LL i=1;i<=m;i++)
{
LL y,x,res=0,t=0;
cin>>y; x=y; int last=0;
while(x/y<=a[n])
{
t++;
int pos=upper_bound(a+1,a+1+n,x)-a;
res+=(s[t][pos-1]-s[t][last]+mod)%mod; last=pos-1;
if (x<a[n]) x*=y; else break;
}
ans=(ans+res%mod*i%mod)%mod;
}
cout<<ans<<endl;
}
}