题干:
给你n个ai和m个pi,求
∑
i
=
1
m
\sum_{i=1}^{m}
∑i=1m(i*
∑
j
=
1
n
\sum_{j=1}^{n}
∑j=1n
⌊
a
j
⌈
log
p
i
a
j
⌉
⌋
\lfloor \frac{a_j}{\lceil \log_{p_i}{a_j} \rceil} \rfloor
⌊⌈logpiaj⌉aj⌋) %
1
0
9
10^9
109的值。
2
≤
p
i
≤
1
0
9
2 \le p_i \le 10^{9}
2≤pi≤109
2
≤
a
i
≤
1
0
9
2 \le a_i \le 10^{9}
2≤ai≤109
思路:
观察
⌊
log
p
i
a
j
⌋
\lfloor \log_{p_i}^{a_j}\rfloor
⌊logpiaj⌋;
当
a
i
a_i
ai=
1
0
9
10^{9}
109、
p
i
p_i
pi=2时取最大值30
当
p
i
p_i
pi=
1
0
9
10^{9}
109、
a
i
a_i
ai=2时取最小值1
又因为是取整,所以分母的范围在[1,30]之间,然后我们可以将分母相同的数放到一起计算,先将
a
i
a_i
ai按从小到大排序,我们就可以用二维数组c[i][j]表示分母为i的分子为
a
j
a_j
aj的前缀和,
我们对于每次输入
p
i
p_i
pi,按
p
i
k
p_i ^ k
pik求出在a[]数组中的上界
p
o
s
i
pos_i
posi,则
∑
j
=
1
n
\sum_{j=1}^{n}
∑j=1n
⌊
a
j
⌈
log
p
i
a
j
⌉
⌋
\lfloor \frac{a_j}{\lceil \log_{p_i}{a_j} \rceil} \rfloor
⌊⌈logpiaj⌉aj⌋就变成了求
∑
j
=
1
n
\sum_{j=1}^{n}
∑j=1nc[k][
p
o
s
i
pos_i
posi](也就是根据分母求不同的前缀和)
注意段错误,前缀和数组(直接用vector最好)、中途的求和、最后的答案用long long型,
a
i
a_i
ai数组和其他的用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;
}