2018ACM浙江省赛 ZOJ 4029 Now Loading!!!(前缀和+二分)

题目描述:

DreamGrid has n n n integers a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an. DreamGrid also has m m m queries, and each time he would like to know the value of ∑ 1 ≤ i ≤ n ⌊ a i ⌈ log ⁡ p a i ⌉ ⌋ \sum\limits_{1 \le i \le n}\Bigl\lfloor \frac{a_i}{\lceil\log_{p}a_i\rceil}\Bigr\rfloor 1inlogpaiai for a given number p p p, where ⌊ x ⌋ = max ⁡ { y ∈ Z ∣ y ≤ x } \lfloor x \rfloor = \max\{y \in \mathbb{Z} \mid y \le x\} x=max{yZyx}, ⌈ x ⌉ = min ⁡ { y ∈ Z ∣ y ≥ x } \lceil x \rceil = \min\{y \in \mathbb{Z} \mid y \ge x\} x=min{yZyx}.

Input

There are multiple test cases. The first line of input is an integer T T T indicating the number of test cases. For each test case:

The first line contains two integers n n n and m m m ( 1 ≤ n , m ≤ 5 × 1 0 5 1 \le n, m \le 5 \times 10^5 1n,m5×105) – the number of integers and the number of queries.

The second line contains n n n integers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,,an ( 2 ≤ a i ≤ 1 0 9 2 \le a_i \le 10^{9} 2ai109).

The third line contains m m m integers p 1 , p 2 , … , p m p_1, p_2, \dots, p_m p1,p2,,pm ( 2 ≤ p i ≤ 1 0 9 2 \le p_i \le 10^{9} 2pi109).

It is guaranteed that neither the sum of all n n n nor the sum of all m m m exceeds 2 × 1 0 6 2 \times 10^6 2×106.

Output

For each test case, output an integer ( ∑ i = 1 m i ⋅ z i )   m o d   1 0 9 (\sum\limits_{i=1}^{m} i \cdot z_i) \bmod 10^9 (i=1mizi)mod109, where z i z_i zi is the answer for the i i 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

翻译:

输入n和m,数组的长度为n,第二行的n个数表示a数组,接下来输入m个p,
对于每一个p,遍历a数组,求得 Z i Z_i Zi

∑ 1 ≤ i ≤ n ⌊ a i ⌈ log ⁡ p a i ⌉ ⌋ \sum\limits_{1 \le i \le n}\Bigl\lfloor \frac{a_i}{\lceil\log_{p}a_i\rceil}\Bigr\rfloor 1inlogpaiai
可以得到m个这样的数 Z i Z_i Zi

输出的结果: ( ∑ i = 1 m i ⋅ z i )   m o d   1 0 9 (\sum\limits_{i=1}^{m} i \cdot z_i) \bmod 10^9 (i=1mizi)mod109

分析:

分母的取值范围:
每一个 a i a_i ai的范围为 [ 2 , 1 0 9 ] [2,10^9] [2,109],每一个p的范围为 [ 2 , 1 0 9 ] [2,10^9] [2,109]
对于分母: ⌈ log ⁡ p a i ⌉ {\lceil\log_{p}a_i\rceil} logpai
int的范围为231-1(即2147483647)

分母的范围可以最小为1,31可以为上限

枚举每一个分母的值,对:
a i ⌈ log ⁡ p a i ⌉ \frac{a_i}{\lceil\log_{p}a_i\rceil} logpaiai 进行前缀和

           for(int k=1; k<=30; k++)///枚举分母
            for(int i=1; i<=n; i++)
                sum[i][k]=sum[i-1][k]+a[i]/k;

输入每一个p,求的一个 Z i Z_i Zi:

p和每一个 a i a_i ai的大小密不可分,并且有向上取整,对a数组从小到大排序,可以用二分解决

初始化两个值 s1=p,s2=1和index=1;
从index=1枚举分母,通过二分找到对应的区间,记录结果,更新s1和s2

        for(int i=1; i<=m; i++)
        {
            LL ans=0,p;
            cin>>p;
            LL s1=p,s2=1;
            int index=1;
            while(true)
            {
                int pos1=upper_bound(a+1,a+1+n,s1)-(a+1);///upper找到第一个大于s1的下标,减去a+1,相当于又减去1,例如 2 3 4 5 upper_bound(3)返回的是位置3,但pos1=2
                int pos2=upper_bound(a+1,a+1+n,s2)-(a+1);
                ans+=sum[pos1][index]-sum[pos2][index];///[pos2,pos1]这个区间的分母都为index
                index++;
                s2=s1;
                s1*=p;///分母为1找完了,再找分母为2,分母为3,,
                if(pos1==n)
                    break;
            }
            res=(res+ans*i)%mod;
        }

完整代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mod=1e9;
const int N=5*1e5+10;
int t,n,m;
LL a[N],sum[N][35];
int main()
{
    cin>>t;
    while (t--)
    {
        cin>>n>>m;
        for (int i=1; i<=n; i++)
            cin>>a[i];
        sort(a+1,a+n+1);
        for(int k=1; k<=30; k++)///枚举分母
            for(int i=1; i<=n; i++)
                sum[i][k]=sum[i-1][k]+a[i]/k;
        LL res=0;
        for(int i=1; i<=m; i++)
        {
            LL ans=0,p;
            cin>>p;
            LL s1=p,s2=1;
            int index=1;
            while(true)
            {
                int pos1=upper_bound(a+1,a+1+n,s1)-(a+1);
                int pos2=upper_bound(a+1,a+1+n,s2)-(a+1);
                ans+=sum[pos1][index]-sum[pos2][index];
                index++;
                s2=s1;
                s1*=p;
                if(pos1==n)
                    break;
            }
            res=(res+ans*i)%mod;
        }
        cout<<res<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值