根据题意可以得出分母的范围为:1-30,对于每个a[j]是p^i到p^(i+1)范围内分母都为i+1,对于每个pi最多可以把a[i]数列分为30组,所以枚举每个pi在a[i]中进行二分查找。然后用前缀和处理下a[i]/j。
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int N=500005+10;
const int MOD=1e9;
#define mem(a,b) memset(a,b,sizeof(a))
int a[N],p[N];
int flag[N],dp[33][N];
void init(int n)
{
for(int i=1;i<=31;i++)
{
dp[i][0]=0;
for(int j=1;j<=n;j++)
{
dp[i][j]=(dp[i][j-1]%MOD+(a[j]/i)%MOD)%MOD;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mem(a,0);
mem(p,0);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
}
sort(a+1,a+1+n);
init(n);
for(int i=1;i<=m;i++)
{
scanf("%d",p+i);
}
ll tmp=1,cnt;
ll sum=0,ans;
for(int i=1;i<=m;i++)
{
tmp=1;
cnt=0;
ans=0;
while(tmp*p[i]<=a[n])
{
int l=1,r=n;
tmp*=p[i];
int x=upper_bound(a+1,a+1+n,tmp)-a-1;
flag[++cnt]=x;
}
if(flag[cnt]<n)
flag[++cnt]=n;
for(int j=1;j<=cnt;j++)
{
ans=(ans%MOD+(dp[j][flag[j]]-dp[j][flag[j-1]])%MOD)%MOD;
}
sum=(sum+ans*i)%MOD;
}
printf("%lld\n",(sum+MOD)%MOD);
}
return 0;
}