zoj-4029 代码

对这种带取整的式子,要考虑是不是很多情况取整后都是一样的值,此题
$$lceil log_pa rceil=iqquad p^{i-1}<ale p^i$$
由于$ale 1e9$ $i$最大的取值为$30$,排序预处理出前缀和,对每个p二分即可

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

using namespace std;
typedef long long ll;
const ll MAXN=5e5+100;
const ll MOD=1e9;
ll a[MAXN],sum[31][MAXN];

int (int argc, char const *argv[]) {

ll T_T;
cin>>T_T;
while(T_T--)
{
ll n,m;
cin>>n>>m;
a[0]=0;
for(int i=1;i<=n;++i)
{
scanf("%lld",&a[i]);
}
sort(a,a+n+1);
for(int i=0;i<31;++i)
sum[i][0]=0;
for(int i=1;i<=n;++i)
{
for(int j=1;j<31;++j)
sum[j][i]=sum[j][i-1]+a[i]/j;
}
ll out=0;
for(int i=1;i<=m;++i)
{
ll p;
scanf("%lld",&p);
ll pp=p;
ll lastp=0;
ll curans=0;
//printf("p==%lldn",p);
for(int j=1;j<31;pp*=p,j++)
{
ll curp=upper_bound(a,a+n+1,pp)-a-1;
//printf(" pp==%lld curp==%lldn",pp,curp);
curans=(curans+sum[j][curp]-sum[j][lastp])%MOD;
lastp=curp;
if(pp>=a[n])
break;
}
curans=curans*i%MOD;
out=(out+curans)%MOD;
//printf("%lldn",out);
}
printf("%lldn",out);
}
return 0;
}