题干:
给你n个ai和m个pi,求
(i*
) %
的值。
思路:
观察
;
当
=
、
=2时取最大值30
当
=
、
=2时取最小值1
又因为是取整,所以分母的范围在[1,30]之间,然后我们可以将分母相同的数放到一起计算,先将
按从小到大排序,我们就可以用二维数组c[i][j]表示分母为i的分子为
的前缀和,
我们对于每次输入
,按
求出在a[]数组中的上界
,则
就变成了求
c[k][
](也就是根据分母求不同的前缀和)
注意段错误,前缀和数组(直接用vector最好)、中途的求和、最后的答案用long long型,
数组和其他的用int
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const ll mod = 1e9;
int x[200000];
ll c[35][200000];
int main()
{
int t,n,m;
ll a;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&x[i]);
}
sort(x+1,x+n+1);
for(int i=1;i<=30;i++){
c[i][0]=0;
for(int j=1;j<=n;j++){
c[i][j]=c[i][j-1]+x[j]/i;
}
}
ll ans=0;
for(int i=1;i<=m;i++){
scanf("%lld",&a);
ll b=a,now=0;
int last=0,t=0;
while(b/a<=x[n])
{
t++;
int pos=upper_bound(x+1,x+1+n,b)-(x+1);
now+=(c[t][pos]-c[t][last]+mod)%mod;
last=pos;
if(b<x[n])
b*=a;
else
break;
}
ans=(ans+now%mod*i%mod)%mod;
}
printf("%lld\n",ans);
}
}
return 0;
}